Skip to content
Snippets Groups Projects
Commit 143f196f authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 575ccb03
No related branches found
No related tags found
No related merge requests found
Showing
with 476 additions and 587 deletions
Loading
Loading
@@ -5,5 +5,5 @@ require 'spec_helper'
describe Types::Tree::TreeEntryType do
it { expect(described_class.graphql_name).to eq('TreeEntry') }
 
it { expect(described_class).to have_graphql_fields(:id, :name, :type, :path, :flat_path, :web_url) }
it { expect(described_class).to have_graphql_fields(:id, :sha, :name, :type, :path, :flat_path, :web_url) }
end
Loading
Loading
@@ -68,4 +68,52 @@ describe 'lograge', type: :request do
subject
end
end
context 'with a log subscriber' do
let(:subscriber) { Lograge::RequestLogSubscriber.new }
let(:event) do
ActiveSupport::Notifications::Event.new(
'process_action.action_controller',
Time.now,
Time.now,
2,
status: 200,
controller: 'HomeController',
action: 'index',
format: 'application/json',
method: 'GET',
path: '/home?foo=bar',
params: {},
db_runtime: 0.02,
view_runtime: 0.01
)
end
let(:log_output) { StringIO.new }
let(:logger) do
Logger.new(log_output).tap { |logger| logger.formatter = ->(_, _, _, msg) { msg } }
end
describe 'with an exception' do
let(:exception) { RuntimeError.new('bad request') }
let(:backtrace) { caller }
before do
allow(exception).to receive(:backtrace).and_return(backtrace)
event.payload[:exception_object] = exception
Lograge.logger = logger
end
it 'adds exception data to log' do
subscriber.process_action(event)
log_data = JSON.parse(log_output.string)
expect(log_data['exception']['class']).to eq('RuntimeError')
expect(log_data['exception']['message']).to eq('bad request')
expect(log_data['exception']['backtrace']).to eq(Gitlab::Profiler.clean_backtrace(backtrace))
end
end
end
end
import Vue from 'vue';
import BoardService from '~/boards/services/board_service';
import BoardsSelector from '~/boards/components/boards_selector.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { TEST_HOST } from 'spec/test_constants';
Loading
Loading
@@ -37,7 +36,6 @@ describe('BoardsSelector', () => {
bulkUpdatePath: '',
boardId: '',
});
window.gl.boardService = new BoardService();
 
allBoardsResponse = Promise.resolve({
data: boards,
Loading
Loading
@@ -46,8 +44,8 @@ describe('BoardsSelector', () => {
data: recentBoards,
});
 
spyOn(BoardService.prototype, 'allBoards').and.returnValue(allBoardsResponse);
spyOn(BoardService.prototype, 'recentBoards').and.returnValue(recentBoardsResponse);
spyOn(boardsStore, 'allBoards').and.returnValue(allBoardsResponse);
spyOn(boardsStore, 'recentBoards').and.returnValue(recentBoardsResponse);
 
const Component = Vue.extend(BoardsSelector);
vm = mountComponent(
Loading
Loading
@@ -94,7 +92,6 @@ describe('BoardsSelector', () => {
 
afterEach(() => {
vm.$destroy();
window.gl.boardService = undefined;
});
 
describe('filtering', () => {
Loading
Loading
Loading
Loading
@@ -11,6 +11,7 @@ describe Gitlab::Ci::Pipeline::Chain::Build do
[{ key: 'first', secret_value: 'world' },
{ key: 'second', secret_value: 'second_world' }]
end
let(:command) do
Gitlab::Ci::Pipeline::Chain::Command.new(
source: :push,
Loading
Loading
@@ -51,12 +52,6 @@ describe Gitlab::Ci::Pipeline::Chain::Build do
.to eq variables_attributes.map(&:with_indifferent_access)
end
 
it 'sets a valid config source' do
step.perform!
expect(pipeline.repository_source?).to be true
end
it 'returns a valid pipeline' do
step.perform!
 
Loading
Loading
Loading
Loading
@@ -18,19 +18,32 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do
seeds_block: nil)
end
 
let(:dependencies) do
[
Gitlab::Ci::Pipeline::Chain::Config::Content.new(pipeline, command),
Gitlab::Ci::Pipeline::Chain::Config::Process.new(pipeline, command),
Gitlab::Ci::Pipeline::Chain::Seed.new(pipeline, command)
]
end
let(:step) { described_class.new(pipeline, command) }
 
let(:config) do
{ rspec: { script: 'rspec' } }
end
 
def run_chain
dependencies.map(&:perform!)
step.perform!
end
before do
stub_ci_pipeline_yaml_file(YAML.dump(config))
end
 
context 'when pipeline doesn not have seeds block' do
before do
step.perform!
run_chain
end
 
it 'does not persist the pipeline' do
Loading
Loading
@@ -66,7 +79,7 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do
end
 
before do
step.perform!
run_chain
end
 
it 'breaks the chain' do
Loading
Loading
@@ -84,16 +97,16 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do
end
 
describe 'pipeline protect' do
subject { step.perform! }
context 'when ref is protected' do
before do
allow(project).to receive(:protected_for?).with('master').and_return(true)
allow(project).to receive(:protected_for?).with('refs/heads/master').and_return(true)
dependencies.map(&:perform!)
end
 
it 'does not protect the pipeline' do
subject
run_chain
 
expect(pipeline.protected).to eq(true)
end
Loading
Loading
@@ -101,7 +114,7 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do
 
context 'when ref is not protected' do
it 'does not protect the pipeline' do
subject
run_chain
 
expect(pipeline.protected).to eq(false)
end
Loading
Loading
@@ -114,7 +127,7 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do
end
 
before do
step.perform!
run_chain
end
 
it 'breaks the chain' do
Loading
Loading
@@ -146,7 +159,7 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do
end
 
it 'populates pipeline with resources described in the seeds block' do
step.perform!
run_chain
 
expect(pipeline).not_to be_persisted
expect(pipeline.variables).not_to be_empty
Loading
Loading
@@ -156,7 +169,7 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do
end
 
it 'has pipeline iid' do
step.perform!
run_chain
 
expect(pipeline.iid).to be > 0
end
Loading
Loading
@@ -168,7 +181,7 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do
end
 
it 'wastes pipeline iid' do
expect { step.perform! }.to raise_error(ActiveRecord::RecordNotSaved)
expect { run_chain }.to raise_error(ActiveRecord::RecordNotSaved)
 
last_iid = InternalId.ci_pipelines
.where(project_id: project.id)
Loading
Loading
@@ -183,14 +196,14 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do
let(:pipeline) { create(:ci_pipeline, project: project) }
 
it 'raises error' do
expect { step.perform! }.to raise_error(described_class::PopulateError)
expect { run_chain }.to raise_error(described_class::PopulateError)
end
end
 
context 'when variables policy is specified' do
shared_examples_for 'a correct pipeline' do
it 'populates pipeline according to used policies' do
step.perform!
run_chain
 
expect(pipeline.stages.size).to eq 1
expect(pipeline.stages.first.statuses.size).to eq 1
Loading
Loading
Loading
Loading
@@ -2,36 +2,38 @@
 
require 'spec_helper'
 
describe Gitlab::Ci::Pipeline::Chain::RemoveUnwantedChatJobs do
let(:project) { create(:project, :repository) }
describe ::Gitlab::Ci::Pipeline::Chain::RemoveUnwantedChatJobs do
let(:project) { create(:project) }
 
let(:pipeline) do
build(:ci_pipeline, project: project)
end
 
let(:command) do
double(:command, project: project, chat_data: { command: 'echo' })
end
before do
stub_ci_pipeline_yaml_file(YAML.dump(rspec: { script: 'rspec' }))
double(:command,
config_processor: double(:processor,
jobs: { echo: double(:job_echo), rspec: double(:job_rspec) }),
project: project,
chat_data: { command: 'echo' })
end
 
describe '#perform!' do
it 'removes unwanted jobs for chat pipelines' do
allow(pipeline).to receive(:chat?).and_return(true)
subject { described_class.new(pipeline, command).perform! }
 
pipeline.config_processor.jobs[:echo] = double(:job)
it 'removes unwanted jobs for chat pipelines' do
expect(pipeline).to receive(:chat?).and_return(true)
 
described_class.new(pipeline, command).perform!
subject
 
expect(pipeline.config_processor.jobs.keys).to eq([:echo])
expect(command.config_processor.jobs.keys).to eq([:echo])
end
end
 
it 'does not remove any jobs for non-chat pipelines' do
described_class.new(pipeline, command).perform!
it 'does not remove any jobs for non chat-pipelines' do
expect(pipeline).to receive(:chat?).and_return(false)
subject
 
expect(pipeline.config_processor.jobs.keys).to eq([:rspec])
expect(command.config_processor.jobs.keys).to eq([:echo, :rspec])
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::Ci::Pipeline::Chain::Seed do
let(:project) { create(:project, :repository) }
let(:user) { create(:user, developer_projects: [project]) }
let(:command) do
Gitlab::Ci::Pipeline::Chain::Command.new(
project: project,
current_user: user,
origin_ref: 'master',
seeds_block: nil)
end
def run_chain(pipeline, command)
[
Gitlab::Ci::Pipeline::Chain::Config::Content.new(pipeline, command),
Gitlab::Ci::Pipeline::Chain::Config::Process.new(pipeline, command)
].map(&:perform!)
described_class.new(pipeline, command).perform!
end
let(:pipeline) { build(:ci_pipeline, project: project) }
describe '#perform!' do
before do
stub_ci_pipeline_yaml_file(YAML.dump(config))
run_chain(pipeline, command)
end
let(:config) do
{ rspec: { script: 'rake' } }
end
it 'allocates next IID' do
expect(pipeline.iid).to be_present
end
it 'sets the seeds in the command object' do
expect(command.stage_seeds).to all(be_a Gitlab::Ci::Pipeline::Seed::Base)
expect(command.stage_seeds.count).to eq 1
end
context 'when no ref policy is specified' do
let(:config) do
{
production: { stage: 'deploy', script: 'cap prod' },
rspec: { stage: 'test', script: 'rspec' },
spinach: { stage: 'test', script: 'spinach' }
}
end
it 'correctly fabricates a stage seeds object' do
seeds = command.stage_seeds
expect(seeds.size).to eq 2
expect(seeds.first.attributes[:name]).to eq 'test'
expect(seeds.second.attributes[:name]).to eq 'deploy'
expect(seeds.dig(0, 0, :name)).to eq 'rspec'
expect(seeds.dig(0, 1, :name)).to eq 'spinach'
expect(seeds.dig(1, 0, :name)).to eq 'production'
end
end
context 'when refs policy is specified' do
let(:pipeline) do
build(:ci_pipeline, project: project, ref: 'feature', tag: true)
end
let(:config) do
{
production: { stage: 'deploy', script: 'cap prod', only: ['master'] },
spinach: { stage: 'test', script: 'spinach', only: ['tags'] }
}
end
it 'returns stage seeds only assigned to master' do
seeds = command.stage_seeds
expect(seeds.size).to eq 1
expect(seeds.first.attributes[:name]).to eq 'test'
expect(seeds.dig(0, 0, :name)).to eq 'spinach'
end
end
context 'when source policy is specified' do
let(:pipeline) { create(:ci_pipeline, source: :schedule) }
let(:config) do
{
production: { stage: 'deploy', script: 'cap prod', only: ['triggers'] },
spinach: { stage: 'test', script: 'spinach', only: ['schedules'] }
}
end
it 'returns stage seeds only assigned to schedules' do
seeds = command.stage_seeds
expect(seeds.size).to eq 1
expect(seeds.first.attributes[:name]).to eq 'test'
expect(seeds.dig(0, 0, :name)).to eq 'spinach'
end
end
context 'when kubernetes policy is specified' do
let(:config) do
{
spinach: { stage: 'test', script: 'spinach' },
production: {
stage: 'deploy',
script: 'cap',
only: { kubernetes: 'active' }
}
}
end
context 'when kubernetes is active' do
context 'when user configured kubernetes from CI/CD > Clusters' do
let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:project) { cluster.project }
let(:pipeline) { build(:ci_pipeline, project: project) }
it 'returns seeds for kubernetes dependent job' do
seeds = command.stage_seeds
expect(seeds.size).to eq 2
expect(seeds.dig(0, 0, :name)).to eq 'spinach'
expect(seeds.dig(1, 0, :name)).to eq 'production'
end
end
end
context 'when kubernetes is not active' do
it 'does not return seeds for kubernetes dependent job' do
seeds = command.stage_seeds
expect(seeds.size).to eq 1
expect(seeds.dig(0, 0, :name)).to eq 'spinach'
end
end
end
context 'when variables policy is specified' do
let(:config) do
{
unit: { script: 'minitest', only: { variables: ['$CI_PIPELINE_SOURCE'] } },
feature: { script: 'spinach', only: { variables: ['$UNDEFINED'] } }
}
end
it 'returns stage seeds only when variables expression is truthy' do
seeds = command.stage_seeds
expect(seeds.size).to eq 1
expect(seeds.dig(0, 0, :name)).to eq 'unit'
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::Ci::Pipeline::Chain::Validate::Config do
set(:project) { create(:project, :repository) }
set(:user) { create(:user) }
let(:command) do
Gitlab::Ci::Pipeline::Chain::Command.new(
project: project,
current_user: user,
save_incompleted: true)
end
let(:pipeline) do
build(:ci_pipeline, project: project)
end
let!(:step) { described_class.new(pipeline, command) }
subject { step.perform! }
context 'when pipeline has no YAML configuration' do
let(:pipeline) do
build_stubbed(:ci_pipeline, project: project)
end
it 'appends errors about missing configuration' do
subject
expect(pipeline.errors.to_a)
.to include 'Missing .gitlab-ci.yml file'
end
it 'breaks the chain' do
subject
expect(step.break?).to be true
end
end
context 'when YAML configuration contains errors' do
before do
stub_ci_pipeline_yaml_file('invalid YAML')
subject
end
it 'appends errors about YAML errors' do
expect(pipeline.errors.to_a)
.to include 'Invalid configuration format'
end
it 'breaks the chain' do
expect(step.break?).to be true
end
context 'when saving incomplete pipeline is allowed' do
let(:command) do
double('command', project: project,
current_user: user,
save_incompleted: true)
end
it 'fails the pipeline' do
subject
expect(pipeline.reload).to be_failed
end
it 'sets a config error failure reason' do
subject
expect(pipeline.reload.config_error?).to eq true
end
end
context 'when saving incomplete pipeline is not allowed' do
let(:command) do
double('command', project: project,
current_user: user,
save_incompleted: false)
end
it 'does not drop pipeline' do
subject
expect(pipeline).not_to be_failed
expect(pipeline).not_to be_persisted
end
end
end
context 'when pipeline contains configuration validation errors' do
before do
stub_ci_pipeline_yaml_file(YAML.dump({
rspec: {
before_script: 10,
script: 'ls -al'
}
}))
subject
end
it 'appends configuration validation errors to pipeline errors' do
expect(pipeline.errors.to_a)
.to include "jobs:rspec:before_script config should be an array containing strings and arrays of strings"
end
it 'breaks the chain' do
expect(step.break?).to be true
end
end
context 'when pipeline is correct and complete' do
before do
stub_ci_pipeline_yaml_file(YAML.dump({
rspec: {
script: 'rspec'
}
}))
subject
end
it 'does not invalidate the pipeline' do
expect(pipeline).to be_valid
end
it 'does not break the chain' do
expect(step.break?).to be false
end
end
context 'when pipeline source is merge request' do
before do
stub_ci_pipeline_yaml_file(YAML.dump(config))
subject
end
let(:pipeline) { build_stubbed(:ci_pipeline, project: project) }
let(:merge_request_pipeline) do
build(:ci_pipeline, source: :merge_request_event, project: project)
end
let(:chain) { described_class.new(merge_request_pipeline, command).tap(&:perform!) }
context "when config contains 'merge_requests' keyword" do
let(:config) { { rspec: { script: 'echo', only: ['merge_requests'] } } }
it 'does not break the chain' do
expect(chain).not_to be_break
end
end
context "when config contains 'merge_request' keyword" do
let(:config) { { rspec: { script: 'echo', only: ['merge_request'] } } }
it 'does not break the chain' do
expect(chain).not_to be_break
end
end
end
end
Loading
Loading
@@ -401,7 +401,7 @@ describe Gitlab::Shell do
 
describe '#add_namespace' do
it 'creates a namespace' do
subject.add_namespace(storage, "mepmep")
Gitlab::GitalyClient::NamespaceService.allow { subject.add_namespace(storage, "mepmep") }
 
expect(TestEnv.storage_dir_exists?(storage, "mepmep")).to be(true)
end
Loading
Loading
@@ -425,8 +425,10 @@ describe Gitlab::Shell do
 
describe '#remove' do
it 'removes the namespace' do
subject.add_namespace(storage, "mepmep")
subject.rm_namespace(storage, "mepmep")
Gitlab::GitalyClient::NamespaceService.allow do
subject.add_namespace(storage, "mepmep")
subject.rm_namespace(storage, "mepmep")
end
 
expect(TestEnv.storage_dir_exists?(storage, "mepmep")).to be(false)
end
Loading
Loading
@@ -434,8 +436,10 @@ describe Gitlab::Shell do
 
describe '#mv_namespace' do
it 'renames the namespace' do
subject.add_namespace(storage, "mepmep")
subject.mv_namespace(storage, "mepmep", "2mep")
Gitlab::GitalyClient::NamespaceService.allow do
subject.add_namespace(storage, "mepmep")
subject.mv_namespace(storage, "mepmep", "2mep")
end
 
expect(TestEnv.storage_dir_exists?(storage, "mepmep")).to be(false)
expect(TestEnv.storage_dir_exists?(storage, "2mep")).to be(true)
Loading
Loading
Loading
Loading
@@ -2221,7 +2221,7 @@ describe Ci::Build do
{ key: 'CI_PAGES_URL', value: project.pages_url, public: true, masked: false },
{ key: 'CI_API_V4_URL', value: 'http://localhost/api/v4', public: true, masked: false },
{ key: 'CI_PIPELINE_IID', value: pipeline.iid.to_s, public: true, masked: false },
{ key: 'CI_CONFIG_PATH', value: pipeline.ci_yaml_file_path, public: true, masked: false },
{ key: 'CI_CONFIG_PATH', value: pipeline.config_path, public: true, masked: false },
{ key: 'CI_PIPELINE_SOURCE', value: pipeline.source, public: true, masked: false },
{ key: 'CI_COMMIT_MESSAGE', value: pipeline.git_commit_message, public: true, masked: false },
{ key: 'CI_COMMIT_TITLE', value: pipeline.git_commit_title, public: true, masked: false },
Loading
Loading
@@ -2667,11 +2667,17 @@ describe Ci::Build do
it { is_expected.to include(deployment_variable) }
end
 
context 'when project has default CI config path' do
let(:ci_config_path) { { key: 'CI_CONFIG_PATH', value: '.gitlab-ci.yml', public: true, masked: false } }
it { is_expected.to include(ci_config_path) }
end
context 'when project has custom CI config path' do
let(:ci_config_path) { { key: 'CI_CONFIG_PATH', value: 'custom', public: true, masked: false } }
 
before do
project.update(ci_config_path: 'custom')
expect_any_instance_of(Project).to receive(:ci_config_path) { 'custom' }
end
 
it { is_expected.to include(ci_config_path) }
Loading
Loading
Loading
Loading
@@ -979,149 +979,6 @@ describe Ci::Pipeline, :mailer do
end
 
describe 'pipeline stages' do
describe '#stage_seeds' do
before do
stub_ci_pipeline_yaml_file(YAML.dump(config))
end
let(:pipeline) { build(:ci_pipeline) }
let(:config) { { rspec: { script: 'rake' } } }
it 'returns preseeded stage seeds object' do
expect(pipeline.stage_seeds)
.to all(be_a Gitlab::Ci::Pipeline::Seed::Base)
expect(pipeline.stage_seeds.count).to eq 1
end
context 'when no refs policy is specified' do
let(:config) do
{ production: { stage: 'deploy', script: 'cap prod' },
rspec: { stage: 'test', script: 'rspec' },
spinach: { stage: 'test', script: 'spinach' } }
end
it 'correctly fabricates a stage seeds object' do
seeds = pipeline.stage_seeds
expect(seeds.size).to eq 2
expect(seeds.first.attributes[:name]).to eq 'test'
expect(seeds.second.attributes[:name]).to eq 'deploy'
expect(seeds.dig(0, 0, :name)).to eq 'rspec'
expect(seeds.dig(0, 1, :name)).to eq 'spinach'
expect(seeds.dig(1, 0, :name)).to eq 'production'
end
end
context 'when refs policy is specified' do
let(:pipeline) do
build(:ci_pipeline, ref: 'feature', tag: true)
end
let(:config) do
{ production: { stage: 'deploy', script: 'cap prod', only: ['master'] },
spinach: { stage: 'test', script: 'spinach', only: ['tags'] } }
end
it 'returns stage seeds only assigned to master to master' do
seeds = pipeline.stage_seeds
expect(seeds.size).to eq 1
expect(seeds.first.attributes[:name]).to eq 'test'
expect(seeds.dig(0, 0, :name)).to eq 'spinach'
end
end
context 'when source policy is specified' do
let(:pipeline) { build(:ci_pipeline, source: :schedule) }
let(:config) do
{ production: { stage: 'deploy', script: 'cap prod', only: ['triggers'] },
spinach: { stage: 'test', script: 'spinach', only: ['schedules'] } }
end
it 'returns stage seeds only assigned to schedules' do
seeds = pipeline.stage_seeds
expect(seeds.size).to eq 1
expect(seeds.first.attributes[:name]).to eq 'test'
expect(seeds.dig(0, 0, :name)).to eq 'spinach'
end
end
context 'when kubernetes policy is specified' do
let(:config) do
{
spinach: { stage: 'test', script: 'spinach' },
production: {
stage: 'deploy',
script: 'cap',
only: { kubernetes: 'active' }
}
}
end
context 'when kubernetes is active' do
context 'when user configured kubernetes from CI/CD > Clusters' do
let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:project) { cluster.project }
let(:pipeline) { build(:ci_pipeline, project: project) }
it 'returns seeds for kubernetes dependent job' do
seeds = pipeline.stage_seeds
expect(seeds.size).to eq 2
expect(seeds.dig(0, 0, :name)).to eq 'spinach'
expect(seeds.dig(1, 0, :name)).to eq 'production'
end
end
end
context 'when kubernetes is not active' do
it 'does not return seeds for kubernetes dependent job' do
seeds = pipeline.stage_seeds
expect(seeds.size).to eq 1
expect(seeds.dig(0, 0, :name)).to eq 'spinach'
end
end
end
context 'when variables policy is specified' do
let(:config) do
{ unit: { script: 'minitest', only: { variables: ['$CI_PIPELINE_SOURCE'] } },
feature: { script: 'spinach', only: { variables: ['$UNDEFINED'] } } }
end
it 'returns stage seeds only when variables expression is truthy' do
seeds = pipeline.stage_seeds
expect(seeds.size).to eq 1
expect(seeds.dig(0, 0, :name)).to eq 'unit'
end
end
end
describe '#seeds_size' do
before do
stub_ci_pipeline_yaml_file(YAML.dump(config))
end
context 'when refs policy is specified' do
let(:config) do
{ production: { stage: 'deploy', script: 'cap prod', only: ['master'] },
spinach: { stage: 'test', script: 'spinach', only: ['tags'] } }
end
let(:pipeline) do
build(:ci_pipeline, ref: 'feature', tag: true)
end
it 'returns real seeds size' do
expect(pipeline.seeds_size).to eq 1
end
end
end
describe 'legacy stages' do
before do
create(:commit_status, pipeline: pipeline,
Loading
Loading
@@ -2194,161 +2051,6 @@ describe Ci::Pipeline, :mailer do
end
end
 
describe '#ci_yaml_file_path' do
subject { pipeline.ci_yaml_file_path }
%i[unknown_source repository_source].each do |source|
context source.to_s do
before do
pipeline.config_source = described_class.config_sources.fetch(source)
end
it 'returns the path from project' do
allow(pipeline.project).to receive(:ci_config_path) { 'custom/path' }
is_expected.to eq('custom/path')
end
it 'returns default when custom path is nil' do
allow(pipeline.project).to receive(:ci_config_path) { nil }
is_expected.to eq('.gitlab-ci.yml')
end
it 'returns default when custom path is empty' do
allow(pipeline.project).to receive(:ci_config_path) { '' }
is_expected.to eq('.gitlab-ci.yml')
end
end
end
context 'when pipeline is for auto-devops' do
before do
pipeline.config_source = 'auto_devops_source'
end
it 'does not return config file' do
is_expected.to be_nil
end
end
end
describe '#set_config_source' do
context 'when pipelines does not contain needed data and auto devops is disabled' do
before do
stub_application_setting(auto_devops_enabled: false)
end
it 'defines source to be unknown' do
pipeline.set_config_source
expect(pipeline).to be_unknown_source
end
end
context 'when pipeline contains all needed data' do
let(:pipeline) do
create(:ci_pipeline, project: project,
sha: '1234',
ref: 'master',
source: :push)
end
context 'when the repository has a config file' do
before do
allow(project.repository).to receive(:gitlab_ci_yml_for)
.and_return('config')
end
it 'defines source to be from repository' do
pipeline.set_config_source
expect(pipeline).to be_repository_source
end
context 'when loading an object' do
let(:new_pipeline) { Ci::Pipeline.find(pipeline.id) }
it 'does not redefine the source' do
# force to overwrite the source
pipeline.unknown_source!
expect(new_pipeline).to be_unknown_source
end
end
end
context 'when the repository does not have a config file' do
let(:implied_yml) { Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps').content }
context 'auto devops enabled' do
before do
allow(project).to receive(:ci_config_path) { 'custom' }
end
it 'defines source to be auto devops' do
pipeline.set_config_source
expect(pipeline).to be_auto_devops_source
end
end
end
end
end
describe '#ci_yaml_file' do
let(:implied_yml) { Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps').content }
context 'the source is unknown' do
before do
pipeline.unknown_source!
end
it 'returns the configuration if found' do
allow(pipeline.project.repository).to receive(:gitlab_ci_yml_for)
.and_return('config')
expect(pipeline.ci_yaml_file).to be_a(String)
expect(pipeline.ci_yaml_file).not_to eq(implied_yml)
expect(pipeline.yaml_errors).to be_nil
end
it 'sets yaml errors if not found' do
expect(pipeline.ci_yaml_file).to be_nil
expect(pipeline.yaml_errors)
.to start_with('Failed to load CI/CD config file')
end
end
context 'the source is the repository' do
before do
pipeline.repository_source!
end
it 'returns the configuration if found' do
allow(pipeline.project.repository).to receive(:gitlab_ci_yml_for)
.and_return('config')
expect(pipeline.ci_yaml_file).to be_a(String)
expect(pipeline.ci_yaml_file).not_to eq(implied_yml)
expect(pipeline.yaml_errors).to be_nil
end
end
context 'when the source is auto_devops_source' do
before do
stub_application_setting(auto_devops_enabled: true)
pipeline.auto_devops_source!
end
it 'finds the implied config' do
expect(pipeline.ci_yaml_file).to eq(implied_yml)
expect(pipeline.yaml_errors).to be_nil
end
end
end
describe '#update_status' do
context 'when pipeline is empty' do
it 'updates does not change pipeline status' do
Loading
Loading
@@ -2894,49 +2596,19 @@ describe Ci::Pipeline, :mailer do
end
 
describe '#has_yaml_errors?' do
before do
stub_ci_pipeline_yaml_file(YAML.dump(config))
end
let(:pipeline) { create(:ci_pipeline) }
context 'when pipeline has errors' do
let(:config) { { rspec: nil } }
it 'contains yaml errors' do
pipeline.config_processor
expect(pipeline).to have_yaml_errors
expect(pipeline.yaml_errors).to include('contains unknown keys')
context 'when yaml_errors is set' do
before do
pipeline.yaml_errors = 'File not found'
end
end
context 'when pipeline has undefined error' do
let(:config) { double(:config) }
it 'contains yaml errors' do
expect(::Gitlab::Ci::YamlProcessor).to receive(:new)
.and_raise(RuntimeError, 'undefined failure')
expect(Gitlab::Sentry).to receive(:track_acceptable_exception)
.with(be_a(RuntimeError), anything)
.and_call_original
pipeline.config_processor
 
it 'returns true if yaml_errors is set' do
expect(pipeline).to have_yaml_errors
expect(pipeline.yaml_errors).to include('Undefined error')
expect(pipeline.yaml_errors).to include('File not foun')
end
end
 
context 'when pipeline does not have errors' do
let(:config) do
{ rspec: { script: 'rake test' } }
end
it 'does not contain yaml errors' do
expect(pipeline).not_to have_yaml_errors
end
it 'returns false if yaml_errors is not set' do
expect(pipeline).not_to have_yaml_errors
end
end
 
Loading
Loading
Loading
Loading
@@ -312,8 +312,8 @@ describe ProjectPresenter do
project.add_developer(user)
allow(project.repository).to receive(:license_blob).and_return(nil)
 
expect(presenter.license_anchor_data).to have_attributes(is_link: true,
label: a_string_including('Add license'),
expect(presenter.license_anchor_data).to have_attributes(is_link: false,
label: a_string_including('Add LICENSE'),
link: presenter.add_license_path)
end
end
Loading
Loading
@@ -322,7 +322,7 @@ describe ProjectPresenter do
it 'returns anchor data' do
allow(project.repository).to receive(:license_blob).and_return(double(name: 'foo'))
 
expect(presenter.license_anchor_data).to have_attributes(is_link: true,
expect(presenter.license_anchor_data).to have_attributes(is_link: false,
label: a_string_including(presenter.license_short_name),
link: presenter.license_path)
end
Loading
Loading
@@ -420,6 +420,7 @@ describe ProjectPresenter do
 
it 'orders the items correctly' do
allow(project.repository).to receive(:readme).and_return(double(name: 'readme'))
allow(project.repository).to receive(:license_blob).and_return(nil)
allow(project.repository).to receive(:changelog).and_return(nil)
allow(project.repository).to receive(:contribution_guide).and_return(double(name: 'foo'))
allow(presenter).to receive(:filename_path).and_return('fake/path')
Loading
Loading
@@ -433,25 +434,54 @@ describe ProjectPresenter do
end
end
 
describe '#empty_repo_statistics_buttons' do
let(:project) { create(:project, :repository) }
describe '#repo_statistics_buttons' do
let(:presenter) { described_class.new(project, current_user: user) }
subject(:empty_repo_statistics_buttons) { presenter.empty_repo_statistics_buttons }
 
before do
project.add_developer(user)
allow(project).to receive(:auto_devops_enabled?).and_return(false)
end
 
it 'orders the items correctly in an empty project' do
expect(empty_repo_statistics_buttons.map(&:label)).to start_with(
a_string_including('New'),
a_string_including('README'),
a_string_including('CHANGELOG'),
a_string_including('CONTRIBUTING'),
a_string_including('CI/CD')
)
context 'empty repo' do
let(:project) { create(:project, :stubbed_repository)}
context 'for a guest user' do
it 'orders the items correctly' do
expect(empty_repo_statistics_buttons.map(&:label)).to start_with(
a_string_including('No license')
)
end
end
context 'for a developer' do
before do
project.add_developer(user)
end
it 'orders the items correctly' do
expect(empty_repo_statistics_buttons.map(&:label)).to start_with(
a_string_including('New'),
a_string_including('README'),
a_string_including('LICENSE'),
a_string_including('CHANGELOG'),
a_string_including('CONTRIBUTING'),
a_string_including('CI/CD')
)
end
end
end
context 'initialized repo' do
let(:project) { create(:project, :repository) }
it 'orders the items correctly' do
expect(empty_repo_statistics_buttons.map(&:label)).to start_with(
a_string_including('README'),
a_string_including('License'),
a_string_including('CHANGELOG'),
a_string_including('CONTRIBUTING')
)
end
end
end
end
Loading
Loading
@@ -200,6 +200,52 @@ describe 'getting an issue list for a project' do
end
end
end
context 'when sorting by relative position' do
let(:sort_project) { create(:project, :public) }
let!(:relative_issue1) { create(:issue, project: sort_project, relative_position: 2000) }
let!(:relative_issue2) { create(:issue, project: sort_project, relative_position: nil) }
let!(:relative_issue3) { create(:issue, project: sort_project, relative_position: 1000) }
let!(:relative_issue4) { create(:issue, project: sort_project, relative_position: nil) }
let!(:relative_issue5) { create(:issue, project: sort_project, relative_position: 500) }
let(:params) { 'sort: RELATIVE_POSITION_ASC' }
def query(issue_params = params)
graphql_query_for(
'project',
{ 'fullPath' => sort_project.full_path },
"issues(#{issue_params}) { pageInfo { endCursor} edges { node { iid dueDate } } }"
)
end
before do
post_graphql(query, current_user: current_user)
end
it_behaves_like 'a working graphql query'
context 'when ascending' do
it 'sorts issues' do
expect(grab_iids).to eq [relative_issue5.iid, relative_issue3.iid, relative_issue1.iid, relative_issue4.iid, relative_issue2.iid]
end
context 'when paginating' do
let(:params) { 'sort: RELATIVE_POSITION_ASC, first: 2' }
it 'sorts issues' do
expect(grab_iids).to eq [relative_issue5.iid, relative_issue3.iid]
cursored_query = query("sort: RELATIVE_POSITION_ASC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
response_data = JSON.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq [relative_issue1.iid, relative_issue4.iid, relative_issue2.iid]
end
end
end
end
end
 
def grab_iids(data = issues_data)
Loading
Loading
Loading
Loading
@@ -1043,14 +1043,12 @@ describe API::MergeRequests do
 
describe 'POST /projects/:id/merge_requests/:merge_request_iid/pipelines' do
before do
allow_any_instance_of(Ci::Pipeline)
.to receive(:ci_yaml_file)
.and_return(YAML.dump({
rspec: {
script: 'ls',
only: ['merge_requests']
}
}))
stub_ci_pipeline_yaml_file(YAML.dump({
rspec: {
script: 'ls',
only: ['merge_requests']
}
}))
end
 
let(:project) do
Loading
Loading
Loading
Loading
@@ -65,6 +65,7 @@ describe Ci::CreatePipelineService do
expect(pipeline.iid).not_to be_nil
expect(pipeline.repository_source?).to be true
expect(pipeline.builds.first).to be_kind_of(Ci::Build)
expect(pipeline.yaml_errors).not_to be_present
end
 
it 'increments the prometheus counter' do
Loading
Loading
@@ -474,6 +475,66 @@ describe Ci::CreatePipelineService do
end
end
 
context 'config evaluation' do
context 'when config is in a file in repository' do
before do
content = YAML.dump(rspec: { script: 'echo' })
stub_ci_pipeline_yaml_file(content)
end
it 'pull it from the repository' do
pipeline = execute_service
expect(pipeline).to be_repository_source
expect(pipeline.builds.map(&:name)).to eq ['rspec']
end
end
context 'when config is from Auto-DevOps' do
before do
stub_ci_pipeline_yaml_file(nil)
allow_any_instance_of(Project).to receive(:auto_devops_enabled?).and_return(true)
end
it 'pull it from Auto-DevOps' do
pipeline = execute_service
expect(pipeline).to be_auto_devops_source
expect(pipeline.builds.map(&:name)).to eq %w[test code_quality build]
end
end
context 'when config is not found' do
before do
stub_ci_pipeline_yaml_file(nil)
end
it 'attaches errors to the pipeline' do
pipeline = execute_service
expect(pipeline.errors.full_messages).to eq ['Missing .gitlab-ci.yml file']
expect(pipeline).not_to be_persisted
end
end
context 'when an unexpected error is raised' do
before do
expect(Gitlab::Ci::YamlProcessor).to receive(:new)
.and_raise(RuntimeError, 'undefined failure')
end
it 'saves error in pipeline' do
pipeline = execute_service
expect(pipeline.yaml_errors).to include('Undefined error')
end
it 'logs error' do
expect(Gitlab::Sentry).to receive(:track_acceptable_exception).and_call_original
execute_service
end
end
end
context 'when yaml is invalid' do
let(:ci_yaml) { 'invalid: file: fiile' }
let(:message) { 'Message' }
Loading
Loading
@@ -539,6 +600,25 @@ describe Ci::CreatePipelineService do
end
end
 
context 'when an unexpected error is raised' do
before do
expect(Gitlab::Ci::YamlProcessor).to receive(:new)
.and_raise(RuntimeError, 'undefined failure')
end
it 'saves error in pipeline' do
pipeline = execute_service
expect(pipeline.yaml_errors).to include('Undefined error')
end
it 'logs error' do
expect(Gitlab::Sentry).to receive(:track_acceptable_exception).and_call_original
execute_service
end
end
context 'when commit contains a [ci skip] directive' do
let(:message) { "some message[ci skip]" }
 
Loading
Loading
Loading
Loading
@@ -18,8 +18,13 @@ module StubGitlabCalls
stub_ci_pipeline_yaml_file(gitlab_ci_yaml)
end
 
def stub_ci_pipeline_yaml_file(ci_yaml)
allow_any_instance_of(Ci::Pipeline).to receive(:ci_yaml_file) { ci_yaml }
def stub_ci_pipeline_yaml_file(ci_yaml_content)
allow_any_instance_of(Repository).to receive(:gitlab_ci_yml_for).and_return(ci_yaml_content)
# Ensure we don't hit auto-devops when config not found in repository
unless ci_yaml_content
allow_any_instance_of(Project).to receive(:auto_devops_enabled?).and_return(false)
end
end
 
def stub_pipeline_modified_paths(pipeline, modified_paths)
Loading
Loading
Loading
Loading
@@ -18,6 +18,14 @@ describe 'projects/show' do
end
 
context 'commit signatures' do
context 'with vue tree view enabled' do
it 'are not rendered via js-signature-container' do
render
expect(rendered).not_to have_css('.js-signature-container')
end
end
context 'with vue tree view disabled' do
before do
stub_feature_flags(vue_file_list: false)
Loading
Loading
@@ -29,13 +37,5 @@ describe 'projects/show' do
expect(rendered).to have_css('.js-signature-container')
end
end
context 'with vue tree view enabled' do
it 'are not rendered via js-signature-container' do
render
expect(rendered).not_to have_css('.js-signature-container')
end
end
end
end
Loading
Loading
@@ -13,8 +13,6 @@ describe 'projects/tree/show' do
let(:tree) { repository.tree(commit.id, path) }
 
before do
stub_feature_flags(vue_file_list: false)
assign(:project, project)
assign(:repository, repository)
assign(:lfs_blob_ids, [])
Loading
Loading
@@ -39,12 +37,15 @@ describe 'projects/tree/show' do
render
 
expect(rendered).to have_css('.js-project-refs-dropdown .dropdown-toggle-text', text: ref)
expect(rendered).to have_css('.readme-holder')
end
end
 
context 'commit signatures' do
context 'with vue tree view disabled' do
before do
stub_feature_flags(vue_file_list: false)
end
it 'rendered via js-signature-container' do
render
 
Loading
Loading
@@ -53,10 +54,6 @@ describe 'projects/tree/show' do
end
 
context 'with vue tree view enabled' do
before do
stub_feature_flags(vue_file_list: true)
end
it 'are not rendered via js-signature-container' do
render
 
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment