diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-06-20 14:10:13 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-06-20 14:10:13 +0300 |
commit | 0ea3fcec397b69815975647f5e2aa5fe944a8486 (patch) | |
tree | 7979381b89d26011bcf9bdc989a40fcc2f1ed4ff /spec/lib/gitlab/ci | |
parent | 72123183a20411a36d607d70b12d57c484394c8e (diff) |
Add latest changes from gitlab-org/gitlab@15-1-stable-eev15.1.0-rc42
Diffstat (limited to 'spec/lib/gitlab/ci')
19 files changed, 531 insertions, 70 deletions
diff --git a/spec/lib/gitlab/ci/build/image_spec.rb b/spec/lib/gitlab/ci/build/image_spec.rb index 630dfcd06bb..8f77a1f60ad 100644 --- a/spec/lib/gitlab/ci/build/image_spec.rb +++ b/spec/lib/gitlab/ci/build/image_spec.rb @@ -28,8 +28,14 @@ RSpec.describe Gitlab::Ci::Build::Image do context 'when image is defined as hash' do let(:entrypoint) { '/bin/sh' } + let(:pull_policy) { %w[always if-not-present] } - let(:job) { create(:ci_build, options: { image: { name: image_name, entrypoint: entrypoint, ports: [80] } } ) } + let(:job) do + create(:ci_build, options: { image: { name: image_name, + entrypoint: entrypoint, + ports: [80], + pull_policy: pull_policy } } ) + end it 'fabricates an object of the proper class' do is_expected.to be_kind_of(described_class) @@ -38,6 +44,7 @@ RSpec.describe Gitlab::Ci::Build::Image do it 'populates fabricated object with the proper attributes' do expect(subject.name).to eq(image_name) expect(subject.entrypoint).to eq(entrypoint) + expect(subject.pull_policy).to eq(pull_policy) end it 'populates the ports' do diff --git a/spec/lib/gitlab/ci/config/entry/image_spec.rb b/spec/lib/gitlab/ci/config/entry/image_spec.rb index e16a9a7a74a..bd1ab5d8c41 100644 --- a/spec/lib/gitlab/ci/config/entry/image_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/image_spec.rb @@ -1,8 +1,16 @@ # frozen_string_literal: true -require 'spec_helper' +require 'fast_spec_helper' +require 'support/helpers/stubbed_feature' +require 'support/helpers/stub_feature_flags' RSpec.describe Gitlab::Ci::Config::Entry::Image do + include StubFeatureFlags + + before do + stub_feature_flags(ci_docker_image_pull_policy: true) + end + let(:entry) { described_class.new(config) } context 'when configuration is a string' do @@ -43,6 +51,12 @@ RSpec.describe Gitlab::Ci::Config::Entry::Image do expect(entry.ports).to be_nil end end + + describe '#pull_policy' do + it "returns nil" do + expect(entry.pull_policy).to be_nil + end + end end context 'when configuration is a hash' do @@ -109,6 +123,56 @@ RSpec.describe Gitlab::Ci::Config::Entry::Image do end end end + + context 'when configuration has pull_policy' do + let(:config) { { name: 'image:1.0', pull_policy: 'if-not-present' } } + + describe '#valid?' do + it 'is valid' do + entry.compose! + + expect(entry).to be_valid + end + + context 'when the feature flag ci_docker_image_pull_policy is disabled' do + before do + stub_feature_flags(ci_docker_image_pull_policy: false) + end + + it 'is not valid' do + entry.compose! + + expect(entry).not_to be_valid + expect(entry.errors).to include('image config contains unknown keys: pull_policy') + end + end + end + + describe '#value' do + it "returns value" do + entry.compose! + + expect(entry.value).to eq( + name: 'image:1.0', + pull_policy: ['if-not-present'] + ) + end + + context 'when the feature flag ci_docker_image_pull_policy is disabled' do + before do + stub_feature_flags(ci_docker_image_pull_policy: false) + end + + it 'is not valid' do + entry.compose! + + expect(entry.value).to eq( + name: 'image:1.0' + ) + end + end + end + end end context 'when entry value is not correct' do diff --git a/spec/lib/gitlab/ci/config/entry/pull_policy_spec.rb b/spec/lib/gitlab/ci/config/entry/pull_policy_spec.rb new file mode 100644 index 00000000000..c35355b10c6 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/pull_policy_spec.rb @@ -0,0 +1,87 @@ +# frozen_string_literal: true + +require 'fast_spec_helper' + +RSpec.describe Gitlab::Ci::Config::Entry::PullPolicy do + let(:entry) { described_class.new(config) } + + describe '#value' do + subject(:value) { entry.value } + + context 'when config value is nil' do + let(:config) { nil } + + it { is_expected.to be_nil } + end + + context 'when retry value is an empty array' do + let(:config) { [] } + + it { is_expected.to eq(nil) } + end + + context 'when retry value is string' do + let(:config) { "always" } + + it { is_expected.to eq(%w[always]) } + end + + context 'when retry value is array' do + let(:config) { %w[always if-not-present] } + + it { is_expected.to eq(%w[always if-not-present]) } + end + end + + describe 'validation' do + subject(:valid?) { entry.valid? } + + context 'when retry value is nil' do + let(:config) { nil } + + it { is_expected.to eq(false) } + end + + context 'when retry value is an empty array' do + let(:config) { [] } + + it { is_expected.to eq(false) } + end + + context 'when retry value is a hash' do + let(:config) { {} } + + it { is_expected.to eq(false) } + end + + context 'when retry value is string' do + let(:config) { "always" } + + it { is_expected.to eq(true) } + + context 'when it is an invalid policy' do + let(:config) { "invalid" } + + it { is_expected.to eq(false) } + end + + context 'when it is an empty string' do + let(:config) { "" } + + it { is_expected.to eq(false) } + end + end + + context 'when retry value is array' do + let(:config) { %w[always if-not-present] } + + it { is_expected.to eq(true) } + + context 'when config contains an invalid policy' do + let(:config) { %w[always invalid] } + + it { is_expected.to eq(false) } + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/rules/rule/changes_spec.rb b/spec/lib/gitlab/ci/config/entry/rules/rule/changes_spec.rb new file mode 100644 index 00000000000..3ed4a9f263f --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/rules/rule/changes_spec.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +require 'fast_spec_helper' + +RSpec.describe Gitlab::Ci::Config::Entry::Rules::Rule::Changes do + let(:factory) do + Gitlab::Config::Entry::Factory.new(described_class) + .value(config) + end + + subject(:entry) { factory.create! } + + before do + entry.compose! + end + + describe '.new' do + context 'when using a string array' do + let(:config) { %w[app/ lib/ spec/ other/* paths/**/*.rb] } + + it { is_expected.to be_valid } + end + + context 'when using an integer array' do + let(:config) { [1, 2] } + + it { is_expected.not_to be_valid } + + it 'returns errors' do + expect(entry.errors).to include(/changes config should be an array of strings/) + end + end + + context 'when using a string' do + let(:config) { 'a regular string' } + + it { is_expected.not_to be_valid } + + it 'reports an error about invalid policy' do + expect(entry.errors).to include(/should be an array of strings/) + end + end + + context 'when using a long array' do + let(:config) { ['app/'] * 51 } + + it { is_expected.not_to be_valid } + + it 'returns errors' do + expect(entry.errors).to include(/has too many entries \(maximum 50\)/) + end + end + + context 'when clause is empty' do + let(:config) {} + + it { is_expected.to be_valid } + end + + context 'when policy strategy does not match' do + let(:config) { 'string strategy' } + + it { is_expected.not_to be_valid } + + it 'returns information about errors' do + expect(entry.errors) + .to include(/should be an array of strings/) + end + end + end + + describe '#value' do + subject(:value) { entry.value } + + context 'when using a string array' do + let(:config) { %w[app/ lib/ spec/ other/* paths/**/*.rb] } + + it { is_expected.to eq(config) } + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb b/spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb index 86270788431..89d349efe8f 100644 --- a/spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb @@ -18,6 +18,10 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules::Rule do let(:entry) { factory.create! } + before do + entry.compose! + end + describe '.new' do subject { entry } @@ -121,7 +125,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules::Rule do it { is_expected.not_to be_valid } it 'returns errors' do - expect(subject.errors).to include(/changes should be an array of strings/) + expect(subject.errors).to include(/changes config should be an array of strings/) end end @@ -131,7 +135,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules::Rule do it { is_expected.not_to be_valid } it 'returns errors' do - expect(subject.errors).to include(/changes is too long \(maximum is 50 characters\)/) + expect(subject.errors).to include(/changes config has too many entries \(maximum 50\)/) end end @@ -434,6 +438,8 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules::Rule do end describe '.default' do + let(:config) {} + it 'does not have default value' do expect(described_class.default).to be_nil end diff --git a/spec/lib/gitlab/ci/config/external/mapper_spec.rb b/spec/lib/gitlab/ci/config/external/mapper_spec.rb index 2d2adf09a42..7e1b31fea6a 100644 --- a/spec/lib/gitlab/ci/config/external/mapper_spec.rb +++ b/spec/lib/gitlab/ci/config/external/mapper_spec.rb @@ -6,7 +6,7 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do include StubRequests let_it_be(:project) { create(:project, :repository) } - let_it_be(:user) { create(:user) } + let_it_be(:user) { project.owner } let(:local_file) { '/lib/gitlab/ci/templates/non-existent-file.yml' } let(:remote_url) { 'https://gitlab.com/gitlab-org/gitlab-foss/blob/1234/.gitlab-ci-1.yml' } @@ -34,6 +34,19 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do describe '#process' do subject(:process) { mapper.process } + shared_examples 'logging config file fetch' do |key, count| + it 'propagates the pipeline logger' do + process + + fetch_content_log_count = mapper + .logger + .observations_hash + .dig(key, 'count') + + expect(fetch_content_log_count).to eq(count) + end + end + context "when single 'include' keyword is defined" do context 'when the string is a local file' do let(:values) do @@ -45,6 +58,8 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do expect(subject).to contain_exactly( an_instance_of(Gitlab::Ci::Config::External::File::Local)) end + + it_behaves_like 'logging config file fetch', 'config_file_fetch_local_content_duration_s', 1 end context 'when the key is a local file hash' do @@ -68,6 +83,8 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do expect(subject).to contain_exactly( an_instance_of(Gitlab::Ci::Config::External::File::Remote)) end + + it_behaves_like 'logging config file fetch', 'config_file_fetch_remote_content_duration_s', 1 end context 'when the key is a remote file hash' do @@ -92,6 +109,8 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do expect(subject).to contain_exactly( an_instance_of(Gitlab::Ci::Config::External::File::Template)) end + + it_behaves_like 'logging config file fetch', 'config_file_fetch_template_content_duration_s', 1 end context 'when the key is a hash of file and remote' do @@ -118,6 +137,8 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do expect(subject).to contain_exactly( an_instance_of(Gitlab::Ci::Config::External::File::Project)) end + + it_behaves_like 'logging config file fetch', 'config_file_fetch_project_content_duration_s', 1 end context "when the key is project's files" do @@ -131,6 +152,8 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do an_instance_of(Gitlab::Ci::Config::External::File::Project), an_instance_of(Gitlab::Ci::Config::External::File::Project)) end + + it_behaves_like 'logging config file fetch', 'config_file_fetch_project_content_duration_s', 2 end end diff --git a/spec/lib/gitlab/ci/jwt_spec.rb b/spec/lib/gitlab/ci/jwt_spec.rb index b0d6f5adfb1..179e2efc0c7 100644 --- a/spec/lib/gitlab/ci/jwt_spec.rb +++ b/spec/lib/gitlab/ci/jwt_spec.rb @@ -160,20 +160,8 @@ RSpec.describe Gitlab::Ci::Jwt do subject(:jwt) { described_class.for_build(build) } - context 'when ci_jwt_signing_key feature flag is disabled' do + context 'when ci_jwt_signing_key is present' do before do - stub_feature_flags(ci_jwt_signing_key: false) - - allow(Rails.application.secrets).to receive(:openid_connect_signing_key).and_return(rsa_key_data) - end - - it_behaves_like 'generating JWT for build' - end - - context 'when ci_jwt_signing_key feature flag is enabled' do - before do - stub_feature_flags(ci_jwt_signing_key: true) - stub_application_setting(ci_jwt_signing_key: rsa_key_data) end diff --git a/spec/lib/gitlab/ci/parsers/coverage/sax_document_spec.rb b/spec/lib/gitlab/ci/parsers/coverage/sax_document_spec.rb index 0580cb9922b..a9851d78f48 100644 --- a/spec/lib/gitlab/ci/parsers/coverage/sax_document_spec.rb +++ b/spec/lib/gitlab/ci/parsers/coverage/sax_document_spec.rb @@ -6,7 +6,7 @@ RSpec.describe Gitlab::Ci::Parsers::Coverage::SaxDocument do subject(:parse_report) { Nokogiri::XML::SAX::Parser.new(described_class.new(coverage_report, project_path, paths)).parse(cobertura) } describe '#parse!' do - let(:coverage_report) { Gitlab::Ci::Reports::CoverageReports.new } + let(:coverage_report) { Gitlab::Ci::Reports::CoverageReport.new } let(:project_path) { 'foo/bar' } let(:paths) { ['app/user.rb'] } diff --git a/spec/lib/gitlab/ci/parsers/security/secret_detection_spec.rb b/spec/lib/gitlab/ci/parsers/security/secret_detection_spec.rb index 1d361e16aad..e8f1d617cb7 100644 --- a/spec/lib/gitlab/ci/parsers/security/secret_detection_spec.rb +++ b/spec/lib/gitlab/ci/parsers/security/secret_detection_spec.rb @@ -39,7 +39,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::SecretDetection do end it "generates expected metadata_version" do - expect(report.findings.first.metadata_version).to eq('3.0') + expect(report.findings.first.metadata_version).to eq('14.1.2') end end end diff --git a/spec/lib/gitlab/ci/pipeline/chain/limit/rate_limit_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/limit/rate_limit_spec.rb index aa8aec2af4a..69d809aee85 100644 --- a/spec/lib/gitlab/ci/pipeline/chain/limit/rate_limit_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/chain/limit/rate_limit_spec.rb @@ -30,10 +30,8 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Chain::Limit::RateLimit, :freeze_time, :c context 'when the limit is exceeded' do before do - allow(Gitlab::ApplicationRateLimiter).to receive(:rate_limits) - .and_return(pipelines_create: { threshold: 1, interval: 1.minute }) - - stub_feature_flags(ci_throttle_pipelines_creation_dry_run: false) + stub_application_setting(pipeline_limit_per_project_user_sha: 1) + stub_feature_flags(ci_enforce_throttle_pipelines_creation_override: false) end it 'does not persist the pipeline' do @@ -55,7 +53,9 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Chain::Limit::RateLimit, :freeze_time, :c class: described_class.name, project_id: project.id, subscription_plan: project.actual_plan_name, - commit_sha: command.sha + commit_sha: command.sha, + throttled: true, + throttle_override: false ) ) @@ -101,9 +101,9 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Chain::Limit::RateLimit, :freeze_time, :c end end - context 'when ci_throttle_pipelines_creation is disabled' do + context 'when ci_enforce_throttle_pipelines_creation is disabled' do before do - stub_feature_flags(ci_throttle_pipelines_creation: false) + stub_feature_flags(ci_enforce_throttle_pipelines_creation: false) end it 'does not break the chain' do @@ -118,16 +118,25 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Chain::Limit::RateLimit, :freeze_time, :c expect(pipeline.errors).to be_empty end - it 'does not log anything' do - expect(Gitlab::AppJsonLogger).not_to receive(:info) + it 'creates a log entry' do + expect(Gitlab::AppJsonLogger).to receive(:info).with( + a_hash_including( + class: described_class.name, + project_id: project.id, + subscription_plan: project.actual_plan_name, + commit_sha: command.sha, + throttled: false, + throttle_override: false + ) + ) perform end end - context 'when ci_throttle_pipelines_creation_dry_run is enabled' do + context 'when ci_enforce_throttle_pipelines_creation_override is enabled' do before do - stub_feature_flags(ci_throttle_pipelines_creation_dry_run: true) + stub_feature_flags(ci_enforce_throttle_pipelines_creation_override: true) end it 'does not break the chain' do @@ -148,7 +157,9 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Chain::Limit::RateLimit, :freeze_time, :c class: described_class.name, project_id: project.id, subscription_plan: project.actual_plan_name, - commit_sha: command.sha + commit_sha: command.sha, + throttled: false, + throttle_override: true ) ) diff --git a/spec/lib/gitlab/ci/pipeline/quota/deployments_spec.rb b/spec/lib/gitlab/ci/pipeline/quota/deployments_spec.rb index 5b0917c5c6f..8f727749ee2 100644 --- a/spec/lib/gitlab/ci/pipeline/quota/deployments_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/quota/deployments_spec.rb @@ -4,9 +4,8 @@ require 'spec_helper' RSpec.describe Gitlab::Ci::Pipeline::Quota::Deployments do let_it_be_with_refind(:namespace) { create(:namespace) } - let_it_be_with_reload(:default_plan) { create(:default_plan) } let_it_be_with_reload(:project) { create(:project, :repository, namespace: namespace) } - let_it_be(:plan_limits) { create(:plan_limits, plan: default_plan) } + let_it_be(:plan_limits) { create(:plan_limits, :default_plan) } let(:pipeline) { build_stubbed(:ci_pipeline, project: project) } diff --git a/spec/lib/gitlab/ci/reports/coverage_report_generator_spec.rb b/spec/lib/gitlab/ci/reports/coverage_report_generator_spec.rb new file mode 100644 index 00000000000..eec218346c2 --- /dev/null +++ b/spec/lib/gitlab/ci/reports/coverage_report_generator_spec.rb @@ -0,0 +1,104 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Ci::Reports::CoverageReportGenerator, factory_default: :keep do + let_it_be(:project) { create_default(:project, :repository).freeze } + let_it_be(:pipeline) { build(:ci_pipeline, :with_coverage_reports) } + + describe '#report' do + subject { described_class.new(pipeline).report } + + let_it_be(:pipeline) { create(:ci_pipeline, :success) } + + shared_examples 'having a coverage report' do + it 'returns coverage reports with collected data' do + expected_files = [ + "auth/token.go", + "auth/rpccredentials.go", + "app/controllers/abuse_reports_controller.rb" + ] + + expect(subject.files.keys).to match_array(expected_files) + end + end + + context 'when pipeline has multiple builds with coverage reports' do + let!(:build_rspec) { create(:ci_build, :success, name: 'rspec', pipeline: pipeline) } + let!(:build_golang) { create(:ci_build, :success, name: 'golang', pipeline: pipeline) } + + before do + create(:ci_job_artifact, :cobertura, job: build_rspec) + create(:ci_job_artifact, :coverage_gocov_xml, job: build_golang) + end + + it_behaves_like 'having a coverage report' + + context 'and it is a child pipeline' do + let!(:pipeline) { create(:ci_pipeline, :success, child_of: build(:ci_pipeline)) } + + it 'returns empty coverage report' do + expect(subject).to be_empty + end + end + end + + context 'when builds are retried' do + let!(:build_rspec) { create(:ci_build, :success, name: 'rspec', retried: true, pipeline: pipeline) } + let!(:build_golang) { create(:ci_build, :success, name: 'golang', retried: true, pipeline: pipeline) } + + before do + create(:ci_job_artifact, :cobertura, job: build_rspec) + create(:ci_job_artifact, :coverage_gocov_xml, job: build_golang) + end + + it 'does not take retried builds into account' do + expect(subject).to be_empty + end + end + + context 'when pipeline does not have any builds with coverage reports' do + it 'returns empty coverage reports' do + expect(subject).to be_empty + end + end + + context 'when pipeline has child pipeline with builds that have coverage reports' do + let!(:child_pipeline) { create(:ci_pipeline, :success, child_of: pipeline) } + + let!(:build_rspec) { create(:ci_build, :success, name: 'rspec', pipeline: child_pipeline) } + let!(:build_golang) { create(:ci_build, :success, name: 'golang', pipeline: child_pipeline) } + + before do + create(:ci_job_artifact, :cobertura, job: build_rspec) + create(:ci_job_artifact, :coverage_gocov_xml, job: build_golang) + end + + it_behaves_like 'having a coverage report' + + context 'when feature flag ci_child_pipeline_coverage_reports is disabled' do + before do + stub_feature_flags(ci_child_pipeline_coverage_reports: false) + end + + it 'returns empty coverage reports' do + expect(subject).to be_empty + end + end + end + + context 'when both parent and child pipeline have builds with coverage reports' do + let!(:child_pipeline) { create(:ci_pipeline, :success, child_of: pipeline) } + + let!(:build_rspec) { create(:ci_build, :success, name: 'rspec', pipeline: pipeline) } + let!(:build_golang) { create(:ci_build, :success, name: 'golang', pipeline: child_pipeline) } + + before do + create(:ci_job_artifact, :cobertura, job: build_rspec) + create(:ci_job_artifact, :coverage_gocov_xml, job: build_golang) + end + + it_behaves_like 'having a coverage report' + end + end +end diff --git a/spec/lib/gitlab/ci/reports/coverage_reports_spec.rb b/spec/lib/gitlab/ci/reports/coverage_report_spec.rb index 41ebae863ee..53646f7dfc0 100644 --- a/spec/lib/gitlab/ci/reports/coverage_reports_spec.rb +++ b/spec/lib/gitlab/ci/reports/coverage_report_spec.rb @@ -2,11 +2,25 @@ require 'spec_helper' -RSpec.describe Gitlab::Ci::Reports::CoverageReports do +RSpec.describe Gitlab::Ci::Reports::CoverageReport do let(:coverage_report) { described_class.new } it { expect(coverage_report.files).to eq({}) } + describe '#empty?' do + context 'when no file has been added' do + it { expect(coverage_report.empty?).to be(true) } + end + + context 'when file has been added' do + before do + coverage_report.add_file('app.rb', { 1 => 0, 2 => 1 }) + end + + it { expect(coverage_report.empty?).to be(false) } + end + end + describe '#pick' do before do coverage_report.add_file('app.rb', { 1 => 0, 2 => 1 }) diff --git a/spec/lib/gitlab/ci/runner_upgrade_check_spec.rb b/spec/lib/gitlab/ci/runner_upgrade_check_spec.rb index f2b4e7573c0..0353432741b 100644 --- a/spec/lib/gitlab/ci/runner_upgrade_check_spec.rb +++ b/spec/lib/gitlab/ci/runner_upgrade_check_spec.rb @@ -51,21 +51,22 @@ RSpec.describe Gitlab::Ci::RunnerUpgradeCheck do end end - context 'with Gitlab::VERSION set to 14.0.123' do + context 'with Gitlab::VERSION set to 14.0.1' do before do - stub_version('14.0.123', 'deadbeef') + stub_version('14.0.1', 'deadbeef') described_class.instance.reset! end context 'with valid params' do where(:runner_version, :expected_result) do - 'v14.1.0-rc3' | :not_available # not available since the GitLab instance is still on 14.0.x - 'v14.1.0~beta.1574.gf6ea9389' | :not_available # suffixes are correctly handled - 'v14.1.0/1.1.0' | :not_available # suffixes are correctly handled - 'v14.1.0' | :not_available # not available since the GitLab instance is still on 14.0.x + 'v15.0.0' | :not_available # not available since the GitLab instance is still on 14.x and a major version might be incompatible + 'v14.1.0-rc3' | :recommended # recommended since even though the GitLab instance is still on 14.0.x, there is a patch release (14.1.1) available which might contain security fixes + 'v14.1.0~beta.1574.gf6ea9389' | :recommended # suffixes are correctly handled + 'v14.1.0/1.1.0' | :recommended # suffixes are correctly handled + 'v14.1.0' | :recommended # recommended since even though the GitLab instance is still on 14.0.x, there is a patch release (14.1.1) available which might contain security fixes 'v14.0.1' | :recommended # recommended upgrade since 14.0.2 is available - 'v14.0.2' | :not_available # not available since 14.0.2 is the latest 14.0.x release available + 'v14.0.2' | :not_available # not available since 14.0.2 is the latest 14.0.x release available within the instance's major.minor version 'v13.10.1' | :available # available upgrade: 14.1.1 'v13.10.1~beta.1574.gf6ea9389' | :available # suffixes are correctly handled 'v13.10.1/1.1.0' | :available # suffixes are correctly handled diff --git a/spec/lib/gitlab/ci/status/build/play_spec.rb b/spec/lib/gitlab/ci/status/build/play_spec.rb index bb406623d2f..ade07a54877 100644 --- a/spec/lib/gitlab/ci/status/build/play_spec.rb +++ b/spec/lib/gitlab/ci/status/build/play_spec.rb @@ -3,9 +3,10 @@ require 'spec_helper' RSpec.describe Gitlab::Ci::Status::Build::Play do - let(:user) { create(:user) } - let(:project) { create(:project, :stubbed_repository) } - let(:build) { create(:ci_build, :manual, project: project) } + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project, :stubbed_repository) } + let_it_be_with_refind(:build) { create(:ci_build, :manual, project: project) } + let(:status) { Gitlab::Ci::Status::Core.new(build, user) } subject { described_class.new(status) } diff --git a/spec/lib/gitlab/ci/status/build/scheduled_spec.rb b/spec/lib/gitlab/ci/status/build/scheduled_spec.rb index b0cd1ac4dc5..a9f9b82767e 100644 --- a/spec/lib/gitlab/ci/status/build/scheduled_spec.rb +++ b/spec/lib/gitlab/ci/status/build/scheduled_spec.rb @@ -3,8 +3,9 @@ require 'spec_helper' RSpec.describe Gitlab::Ci::Status::Build::Scheduled do - let(:user) { create(:user) } - let(:project) { create(:project, :stubbed_repository) } + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project, :stubbed_repository) } + let(:build) { create(:ci_build, :scheduled, project: project) } let(:status) { Gitlab::Ci::Status::Core.new(build, user) } diff --git a/spec/lib/gitlab/ci/trace/archive_spec.rb b/spec/lib/gitlab/ci/trace/archive_spec.rb index 5e965f94347..3ae0e5d1f0e 100644 --- a/spec/lib/gitlab/ci/trace/archive_spec.rb +++ b/spec/lib/gitlab/ci/trace/archive_spec.rb @@ -29,35 +29,59 @@ RSpec.describe Gitlab::Ci::Trace::Archive do let(:stream) { StringIO.new(trace, 'rb') } let(:src_checksum) { Digest::MD5.hexdigest(trace) } - context 'when the object store is disabled' do - before do - stub_artifacts_object_storage(enabled: false) + shared_examples 'valid' do + it 'does not count as invalid' do + subject.execute!(stream) + + expect(metrics) + .not_to have_received(:increment_error_counter) + .with(error_reason: :archive_invalid_checksum) end + end - it 'skips validation' do + shared_examples 'local checksum only' do + it 'generates only local checksum' do subject.execute!(stream) + expect(trace_metadata.checksum).to eq(src_checksum) expect(trace_metadata.remote_checksum).to be_nil - expect(metrics) - .not_to have_received(:increment_error_counter) - .with(error_reason: :archive_invalid_checksum) end end - context 'with background_upload enabled' do + shared_examples 'skips validations' do + it_behaves_like 'valid' + it_behaves_like 'local checksum only' + end + + shared_context 'with FIPS' do + context 'with FIPS enabled', :fips_mode do + it_behaves_like 'valid' + + it 'does not generate md5 checksums' do + subject.execute!(stream) + + expect(trace_metadata.checksum).to be_nil + expect(trace_metadata.remote_checksum).to be_nil + end + end + end + + context 'when the object store is disabled' do before do - stub_artifacts_object_storage(background_upload: true) + stub_artifacts_object_storage(enabled: false) end - it 'skips validation' do - subject.execute!(stream) + it_behaves_like 'skips validations' + include_context 'with FIPS' + end - expect(trace_metadata.checksum).to eq(src_checksum) - expect(trace_metadata.remote_checksum).to be_nil - expect(metrics) - .not_to have_received(:increment_error_counter) - .with(error_reason: :archive_invalid_checksum) + context 'with background_upload enabled' do + before do + stub_artifacts_object_storage(background_upload: true) end + + it_behaves_like 'skips validations' + include_context 'with FIPS' end context 'with direct_upload enabled' do @@ -65,27 +89,26 @@ RSpec.describe Gitlab::Ci::Trace::Archive do stub_artifacts_object_storage(direct_upload: true) end - it 'validates the archived trace' do + it_behaves_like 'valid' + + it 'checksums match' do subject.execute!(stream) expect(trace_metadata.checksum).to eq(src_checksum) expect(trace_metadata.remote_checksum).to eq(src_checksum) - expect(metrics) - .not_to have_received(:increment_error_counter) - .with(error_reason: :archive_invalid_checksum) end context 'when the checksum does not match' do let(:invalid_remote_checksum) { SecureRandom.hex } before do - expect(::Gitlab::Ci::Trace::RemoteChecksum) + allow(::Gitlab::Ci::Trace::RemoteChecksum) .to receive(:new) .with(an_instance_of(Ci::JobArtifact)) .and_return(double(md5_checksum: invalid_remote_checksum)) end - it 'validates the archived trace' do + it 'counts as invalid' do subject.execute!(stream) expect(trace_metadata.checksum).to eq(src_checksum) @@ -94,7 +117,11 @@ RSpec.describe Gitlab::Ci::Trace::Archive do .to have_received(:increment_error_counter) .with(error_reason: :archive_invalid_checksum) end + + include_context 'with FIPS' end + + include_context 'with FIPS' end end end diff --git a/spec/lib/gitlab/ci/variables/builder_spec.rb b/spec/lib/gitlab/ci/variables/builder_spec.rb index e13a0993fa8..b0704ad7f50 100644 --- a/spec/lib/gitlab/ci/variables/builder_spec.rb +++ b/spec/lib/gitlab/ci/variables/builder_spec.rb @@ -64,6 +64,8 @@ RSpec.describe Gitlab::Ci::Variables::Builder do value: project.path }, { key: 'CI_PROJECT_TITLE', value: project.title }, + { key: 'CI_PROJECT_DESCRIPTION', + value: project.description }, { key: 'CI_PROJECT_PATH', value: project.full_path }, { key: 'CI_PROJECT_PATH_SLUG', diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb index 1910057622b..3dd9ca35881 100644 --- a/spec/lib/gitlab/ci/yaml_processor_spec.rb +++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb @@ -7,7 +7,7 @@ module Gitlab RSpec.describe YamlProcessor do include StubRequests - subject { described_class.new(config, user: nil).execute } + subject(:processor) { described_class.new(config, user: nil).execute } shared_examples 'returns errors' do |error_message| it 'adds a message when an error is encountered' do @@ -965,6 +965,51 @@ module Gitlab }) end end + + context 'when image has pull_policy' do + let(:config) do + <<~YAML + image: + name: ruby:2.7 + pull_policy: if-not-present + + test: + script: exit 0 + YAML + end + + it { is_expected.to be_valid } + + it "returns image and service when defined" do + expect(processor.stage_builds_attributes("test")).to contain_exactly({ + stage: "test", + stage_idx: 2, + name: "test", + only: { refs: %w[branches tags] }, + options: { + script: ["exit 0"], + image: { name: "ruby:2.7", pull_policy: ["if-not-present"] } + }, + allow_failure: false, + when: "on_success", + job_variables: [], + root_variables_inheritance: true, + scheduling_type: :stage + }) + end + + context 'when the feature flag ci_docker_image_pull_policy is disabled' do + before do + stub_feature_flags(ci_docker_image_pull_policy: false) + end + + it { is_expected.not_to be_valid } + + it "returns no job" do + expect(processor.jobs).to eq({}) + end + end + end end describe 'Variables' do |