Commit 4db9eeb4 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 8a3fdede
...@@ -62,6 +62,34 @@ export default { ...@@ -62,6 +62,34 @@ export default {
showStacktrace() { showStacktrace() {
return Boolean(!this.loadingStacktrace && this.stacktrace && this.stacktrace.length); return Boolean(!this.loadingStacktrace && this.stacktrace && this.stacktrace.length);
}, },
errorTitle() {
return `${this.error.title}`;
},
errorUrl() {
return sprintf(__('Sentry event: %{external_url}'), {
external_url: this.error.external_url,
});
},
errorFirstSeen() {
return sprintf(__('First seen: %{first_seen}'), { first_seen: this.error.first_seen });
},
errorLastSeen() {
return sprintf(__('Last seen: %{last_seen}'), { last_seen: this.error.last_seen });
},
errorCount() {
return sprintf(__('Events: %{count}'), { count: this.error.count });
},
errorUserCount() {
return sprintf(__('Users: %{user_count}'), { user_count: this.error.user_count });
},
issueLink() {
return `${this.issueProjectPath}?issue[title]=${encodeURIComponent(
this.errorTitle,
)}&issue[description]=${encodeURIComponent(this.issueDescription)}`;
},
issueDescription() {
return `${this.errorUrl}${this.errorFirstSeen}${this.errorLastSeen}${this.errorCount}${this.errorUserCount}`;
},
}, },
mounted() { mounted() {
this.startPollingDetails(this.issueDetailsPath); this.startPollingDetails(this.issueDetailsPath);
...@@ -86,7 +114,7 @@ export default { ...@@ -86,7 +114,7 @@ export default {
<div v-else-if="showDetails" class="error-details"> <div v-else-if="showDetails" class="error-details">
<div class="top-area align-items-center justify-content-between py-3"> <div class="top-area align-items-center justify-content-between py-3">
<span v-if="!loadingStacktrace && stacktrace" v-html="reported"></span> <span v-if="!loadingStacktrace && stacktrace" v-html="reported"></span>
<gl-button variant="success" :href="issueProjectPath"> <gl-button variant="success" :href="issueLink">
{{ __('Create issue') }} {{ __('Create issue') }}
</gl-button> </gl-button>
</div> </div>
......
...@@ -205,14 +205,6 @@ module Ci ...@@ -205,14 +205,6 @@ module Ci
scope :internal, -> { where(source: internal_sources) } scope :internal, -> { where(source: internal_sources) }
scope :ci_sources, -> { where(config_source: ci_sources_values) } scope :ci_sources, -> { where(config_source: ci_sources_values) }
scope :sort_by_merge_request_pipelines, -> do
sql = 'CASE ci_pipelines.source WHEN (?) THEN 0 ELSE 1 END, ci_pipelines.id DESC'
query = ApplicationRecord.send(:sanitize_sql_array, [sql, sources[:merge_request_event]]) # rubocop:disable GitlabSecurity/PublicSend
order(Arel.sql(query))
end
scope :for_user, -> (user) { where(user: user) } scope :for_user, -> (user) { where(user: user) }
scope :for_sha, -> (sha) { where(sha: sha) } scope :for_sha, -> (sha) { where(sha: sha) }
scope :for_source_sha, -> (source_sha) { where(source_sha: source_sha) } scope :for_source_sha, -> (source_sha) { where(source_sha: source_sha) }
...@@ -221,22 +213,6 @@ module Ci ...@@ -221,22 +213,6 @@ module Ci
scope :for_id, -> (id) { where(id: id) } scope :for_id, -> (id) { where(id: id) }
scope :created_after, -> (time) { where('ci_pipelines.created_at > ?', time) } scope :created_after, -> (time) { where('ci_pipelines.created_at > ?', time) }
scope :triggered_by_merge_request, -> (merge_request) do
where(source: :merge_request_event, merge_request: merge_request)
end
scope :detached_merge_request_pipelines, -> (merge_request, sha) do
triggered_by_merge_request(merge_request).for_sha(sha)
end
scope :merge_request_pipelines, -> (merge_request, source_sha) do
triggered_by_merge_request(merge_request).for_source_sha(source_sha)
end
scope :triggered_for_branch, -> (ref) do
where(source: branch_pipeline_sources).where(ref: ref, tag: false)
end
scope :with_reports, -> (reports_scope) do scope :with_reports, -> (reports_scope) do
where('EXISTS (?)', ::Ci::Build.latest.with_reports(reports_scope).where('ci_pipelines.id=ci_builds.commit_id').select(1)) where('EXISTS (?)', ::Ci::Build.latest.with_reports(reports_scope).where('ci_pipelines.id=ci_builds.commit_id').select(1))
end end
...@@ -344,10 +320,6 @@ module Ci ...@@ -344,10 +320,6 @@ module Ci
sources.reject { |source| source == "external" }.values sources.reject { |source| source == "external" }.values
end end
def self.branch_pipeline_sources
@branch_pipeline_sources ||= sources.reject { |source| source == 'merge_request_event' }.values
end
def self.ci_sources_values def self.ci_sources_values
config_sources.values_at(:repository_source, :auto_devops_source, :unknown_source) config_sources.values_at(:repository_source, :auto_devops_source, :unknown_source)
end end
......
...@@ -1245,16 +1245,8 @@ class MergeRequest < ApplicationRecord ...@@ -1245,16 +1245,8 @@ class MergeRequest < ApplicationRecord
end end
def all_pipelines def all_pipelines
return Ci::Pipeline.none unless source_project
shas = all_commit_shas
strong_memoize(:all_pipelines) do strong_memoize(:all_pipelines) do
Ci::Pipeline.from_union( MergeRequest::Pipelines.new(self).all
[source_project.ci_pipelines.merge_request_pipelines(self, shas),
source_project.ci_pipelines.detached_merge_request_pipelines(self, shas),
source_project.ci_pipelines.triggered_for_branch(source_branch).for_sha(shas)],
remove_duplicates: false).sort_by_merge_request_pipelines
end end
end end
......
# frozen_string_literal: true
# A state object to centralize logic related to merge request pipelines
class MergeRequest::Pipelines
include Gitlab::Utils::StrongMemoize
EVENT = 'merge_request_event'
def initialize(merge_request)
@merge_request = merge_request
end
attr_reader :merge_request
delegate :all_commit_shas, :source_project, :source_branch, to: :merge_request
def all
return Ci::Pipeline.none unless source_project
strong_memoize(:all_pipelines) do
pipelines = Ci::Pipeline.from_union(
[source_pipelines, detached_pipelines, triggered_for_branch],
remove_duplicates: false)
sort(pipelines)
end
end
private
def triggered_by_merge_request
source_project.ci_pipelines
.where(source: :merge_request_event, merge_request: merge_request)
end
def detached_pipelines
triggered_by_merge_request.for_sha(all_commit_shas)
end
def source_pipelines
triggered_by_merge_request.for_source_sha(all_commit_shas)
end
def triggered_for_branch
source_project.ci_pipelines
.where(source: branch_pipeline_sources, ref: source_branch, tag: false)
.for_sha(all_commit_shas)
end
def sources
::Ci::Pipeline.sources
end
def branch_pipeline_sources
strong_memoize(:branch_pipeline_sources) do
sources.reject { |source| source == EVENT }.values
end
end
def sort(pipelines)
sql = 'CASE ci_pipelines.source WHEN (?) THEN 0 ELSE 1 END, ci_pipelines.id DESC'
query = ApplicationRecord.send(:sanitize_sql_array, [sql, sources[:merge_request_event]]) # rubocop:disable GitlabSecurity/PublicSend
pipelines.order(Arel.sql(query))
end
end
...@@ -273,6 +273,65 @@ git config core.sshCommand "ssh -o IdentitiesOnly=yes -i ~/.ssh/private-key-file ...@@ -273,6 +273,65 @@ git config core.sshCommand "ssh -o IdentitiesOnly=yes -i ~/.ssh/private-key-file
This will not use the SSH Agent and requires at least Git 2.10. This will not use the SSH Agent and requires at least Git 2.10.
## Multiple accounts on a single GitLab instance
The [per-repository](#per-repository-ssh-keys) method also works for using
multiple accounts within a single GitLab instance.
Alternatively, it is possible to directly assign aliases to hosts in
`~.ssh/config`. SSH and, by extension, Git will fail to log in if there is
an `IdentityFile` set outside of a `Host` block in `.ssh/config`. This is
due to how SSH assembles `IdentityFile` entries and is not changed by
setting `IdentitiesOnly` to `yes`. `IdentityFile` entries should point to
the private key of an SSH key pair.
NOTE: **Note:**
Private and public keys should be readable by the user only. Accomplish this
on Linux and macOS by running: `chmod 0400 ~/.ssh/<example_ssh_key>` and
`chmod 0400 ~/.ssh/<example_sh_key.pub>`.
```conf
# User1 Account Identity
Host <user_1.gitlab.com>
Hostname gitlab.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/<example_ssh_key1>
# User2 Account Identity
Host <user_2.gitlab.com>
Hostname gitlab.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/<example_ssh_key2>
```
NOTE: **Note:**
The example `Host` aliases are defined as `user_1.gitlab.com` and
`user_2.gitlab.com` for efficiency and transparency. Advanced configurations
are more difficult to maintain; using this type of alias makes it easier to
understand when using other tools such as `git remote` subcommands. SSH
would understand any string as a `Host` alias thus `Tanuki1` and `Tanuki2`,
despite giving very little context as to where they point, would also work.
Cloning the `gitlab` repository normally looks like this:
```sh
git clone git@gitlab.com:gitlab-org/gitlab.git
```
To clone it for `user_1`, replace `gitlab.com` with the SSH alias `user_1.gitlab.com`:
```sh
git clone git@<user_1.gitlab.com>:gitlab-org/gitlab.git
```
Fix a previously cloned repository using the `git remote` command.
The example below assumes the remote repository is aliased as `origin`.
```sh
git remote set-url origin git@<user_1.gitlab.com>:gitlab-org/gitlab.git
```
## Deploy keys ## Deploy keys
### Per-repository deploy keys ### Per-repository deploy keys
......
...@@ -6940,6 +6940,9 @@ msgstr "" ...@@ -6940,6 +6940,9 @@ msgstr ""
msgid "Events" msgid "Events"
msgstr "" msgstr ""
msgid "Events: %{count}"
msgstr ""
msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again." msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
msgstr "" msgstr ""
...@@ -7599,6 +7602,9 @@ msgstr "" ...@@ -7599,6 +7602,9 @@ msgstr ""
msgid "First seen" msgid "First seen"
msgstr "" msgstr ""
msgid "First seen: %{first_seen}"
msgstr ""
msgid "Fixed date" msgid "Fixed date"
msgstr "" msgstr ""
...@@ -10038,6 +10044,9 @@ msgstr "" ...@@ -10038,6 +10044,9 @@ msgstr ""
msgid "Last seen" msgid "Last seen"
msgstr "" msgstr ""
msgid "Last seen: %{last_seen}"
msgstr ""
msgid "Last successful update" msgid "Last successful update"
msgstr "" msgstr ""
...@@ -15510,6 +15519,9 @@ msgstr "" ...@@ -15510,6 +15519,9 @@ msgstr ""
msgid "Sentry event" msgid "Sentry event"
msgstr "" msgstr ""
msgid "Sentry event: %{external_url}"
msgstr ""
msgid "Sep" msgid "Sep"
msgstr "" msgstr ""
...@@ -16415,6 +16427,12 @@ msgstr "" ...@@ -16415,6 +16427,12 @@ msgstr ""
msgid "Stage changes" msgid "Stage changes"
msgstr "" msgstr ""
msgid "Stage data updated"
msgstr ""
msgid "Stage removed"
msgstr ""
msgid "Staged" msgid "Staged"
msgstr "" msgstr ""
...@@ -17524,6 +17542,9 @@ msgstr "" ...@@ -17524,6 +17542,9 @@ msgstr ""
msgid "There was an error removing the e-mail." msgid "There was an error removing the e-mail."
msgstr "" msgstr ""
msgid "There was an error removing your custom stage, please try again"
msgstr ""
msgid "There was an error resetting group pipeline minutes." msgid "There was an error resetting group pipeline minutes."
msgstr "" msgstr ""
...@@ -19196,6 +19217,9 @@ msgstr "" ...@@ -19196,6 +19217,9 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use." msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr "" msgstr ""
msgid "Users: %{user_count}"
msgstr ""
msgid "UsersSelect|%{name} + %{length} more" msgid "UsersSelect|%{name} + %{length} more"
msgstr "" msgstr ""
......
...@@ -83,13 +83,34 @@ describe('ErrorDetails', () => { ...@@ -83,13 +83,34 @@ describe('ErrorDetails', () => {
expect(wrapper.find(Stacktrace).exists()).toBe(false); expect(wrapper.find(Stacktrace).exists()).toBe(false);
}); });
it('should allow a blank issue to be created', () => { it('should allow an issue to be created with title and description', () => {
store.state.details.loading = false; store.state.details.loading = false;
store.state.details.error.id = 1; store.state.details.error = {
id: 1,
title: 'Issue title',
external_url: 'http://sentry.gitlab.net/gitlab',
first_seen: '2017-05-26T13:32:48Z',
last_seen: '2018-05-26T13:32:48Z',
count: 12,
user_count: 2,
};
mountComponent(); mountComponent();
const button = wrapper.find(GlButton); const button = wrapper.find(GlButton);
const title = 'Issue title';
const url = 'Sentry event: http://sentry.gitlab.net/gitlab';
const firstSeen = 'First seen: 2017-05-26T13:32:48Z';
const lastSeen = 'Last seen: 2018-05-26T13:32:48Z';
const count = 'Events: 12';
const userCount = 'Users: 2';
const issueDescription = `${url}${firstSeen}${lastSeen}${count}${userCount}`;
const issueLink = `/test-project/issues/new?issue[title]=${encodeURIComponent(
title,
)}&issue[description]=${encodeURIComponent(issueDescription)}`;
expect(button.exists()).toBe(true); expect(button.exists()).toBe(true);
expect(button.attributes().href).toBe(wrapper.props().issueProjectPath); expect(button.attributes().href).toBe(issueLink);
}); });
describe('Stacktrace', () => { describe('Stacktrace', () => {
......
...@@ -75,71 +75,6 @@ describe Ci::Pipeline, :mailer do ...@@ -75,71 +75,6 @@ describe Ci::Pipeline, :mailer do
end end
end end
describe '.sort_by_merge_request_pipelines' do
subject { described_class.sort_by_merge_request_pipelines }
context 'when branch pipelines exist' do
let!(:branch_pipeline_1) { create(:ci_pipeline, source: :push) }
let!(:branch_pipeline_2) { create(:ci_pipeline, source: :push) }
it 'returns pipelines order by id' do
expect(subject).to eq([branch_pipeline_2,
branch_pipeline_1])
end
end
context 'when merge request pipelines exist' do
let!(:merge_request_pipeline_1) do
create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request)
end
let!(:merge_request_pipeline_2) do
create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request)
end
let(:merge_request) do
create(:merge_request,
source_project: project,
source_branch: 'feature',
target_project: project,
target_branch: 'master')
end
it 'returns pipelines order by id' do
expect(subject).to eq([merge_request_pipeline_2,
merge_request_pipeline_1])
end
end
context 'when both branch pipeline and merge request pipeline exist' do
let!(:branch_pipeline_1) { create(:ci_pipeline, source: :push) }
let!(:branch_pipeline_2) { create(:ci_pipeline, source: :push) }
let!(:merge_request_pipeline_1) do
create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request)
end
let!(:merge_request_pipeline_2) do
create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request)
end
let(:merge_request) do
create(:merge_request,
source_project: project,
source_branch: 'feature',
target_project: project,
target_branch: 'master')
end
it 'returns merge request pipeline first' do
expect(subject).to eq([merge_request_pipeline_2,
merge_request_pipeline_1,
branch_pipeline_2,
branch_pipeline_1])
end
end
end
describe '.for_sha' do describe '.for_sha' do
subject { described_class.for_sha(sha) } subject { described_class.for_sha(sha) }
...@@ -226,39 +161,6 @@ describe Ci::Pipeline, :mailer do ...@@ -226,39 +161,6 @@ describe Ci::Pipeline, :mailer do
end end
end end
describe '.detached_merge_request_pipelines' do
subject { described_class.detached_merge_request_pipelines(merge_request, sha) }
let!(:pipeline) do
create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, sha: merge_request.diff_head_sha)
end
let(:merge_request) { create(:merge_request) }
let(:sha) { merge_request.diff_head_sha }
it 'returns detached merge request pipelines' do
is_expected.to eq([pipeline])
end
context 'when sha does not exist' do
let(:sha) { 'abc' }
it 'returns empty array' do
is_expected.to be_empty
end
end
context 'when pipeline is merge request pipeline' do
let!(:pipeline) do
create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, source_sha: merge_request.diff_head_sha)
end
it 'returns empty array' do
is_expected.to be_empty
end
end
end
describe '#detached_merge_request_pipeline?' do describe '#detached_merge_request_pipeline?' do
subject { pipeline.detached_merge_request_pipeline? } subject { pipeline.detached_merge_request_pipeline? }
...@@ -278,39 +180,6 @@ describe Ci::Pipeline, :mailer do ...@@ -278,39 +180,6 @@ describe Ci::Pipeline, :mailer do
end end
end end
describe '.merge_request_pipelines' do
subject { described_class.merge_request_pipelines(merge_request, source_sha) }
let!(:pipeline) do
create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, source_sha: merge_request.diff_head_sha)
end
let(:merge_request) { create(:merge_request) }
let(:source_sha) { merge_request.diff_head_sha }
it 'returns merge pipelines' do
is_expected.to eq([pipeline])
end
context 'when source sha is empty' do
let(:source_sha) { nil }
it 'returns empty array' do
is_expected.to be_empty
end
end
context 'when pipeline is detached merge request pipeline' do
let!(:pipeline) do
create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, sha: merge_request.diff_head_sha)
end
it 'returns empty array' do
is_expected.to be_empty
end
end
end
describe '#merge_request_pipeline?' do describe '#merge_request_pipeline?' do
subject { pipeline.merge_request_pipeline? } subject { pipeline.merge_request_pipeline? }
...@@ -499,50 +368,6 @@ describe Ci::Pipeline, :mailer do ...@@ -499,50 +368,6 @@ describe Ci::Pipeline, :mailer do
end end
end end
describe '.triggered_for_branch' do
subject { described_class.triggered_for_branch(ref) }
let(:project) { create(:project, :repository) }
let(:ref) { 'feature' }
let!(:pipeline) { create(:ci_pipeline, ref: ref) }
it 'returns the pipeline' do
is_expected.to eq([pipeline])
end
context 'when sha is not specified' do
it 'returns the pipeline' do
expect(described_class.triggered_for_branch(ref)).to eq([pipeline])
end
end
context 'when pipeline is triggered for tag' do
let(:ref) { 'v1.1.0' }
let!(:pipeline) { create(:ci_pipeline, ref: ref, tag: true) }
it 'does not return the pipeline' do
is_expected.to be_empty
end
end
context 'when pipeline is triggered for merge_request' do
let!(:merge_request) do
create(:merge_request,
:with_merge_request_pipeline,
source_project: project,
source_branch: ref,
target_project: project,
target_branch: 'master')
end
let(:pipeline) { merge_request.pipelines_for_merge_request.first }
it 'does not return the pipeline' do
is_expected.to be_empty
end
end
end
describe '.with_reports' do describe '.with_reports' do
subject { described_class.with_reports(Ci::JobArtifact.test_reports) } subject { described_class.with_reports(Ci::JobArtifact.test_reports) }
......
# frozen_string_literal: true
require 'spec_helper'
describe MergeRequest::Pipelines do
describe '#all' do
let(:merge_request) { create(:merge_request) }
let(:project) { merge_request.source_project }
subject { described_class.new(merge_request) }
shared_examples 'returning pipelines with proper ordering' do
let!(:all_pipelines) do
merge_request.all_commit_shas.map do |sha|
create(:ci_empty_pipeline,
project: project, sha: sha, ref: merge_request.source_branch)
end
end
it 'returns all pipelines' do
expect(subject.all).not_to be_empty
expect(subject.all).to eq(all_pipelines.reverse)
end
end
context 'with single merge_request_diffs' do
it_behaves_like 'returning pipelines with proper ordering'
end
context 'with multiple irrelevant merge_request_diffs' do
before do
merge_request.update(target_branch: 'v1.0.0')
end
it_behaves_like 'returning pipelines with proper ordering'
end
context 'with unsaved merge request' do
let(:merge_request) { build(:merge_request) }
let!(:pipeline) do
create(:ci_empty_pipeline, project: project,
sha: merge_request.diff_head_sha, ref: merge_request.source_branch)
end
it 'returns pipelines from diff_head_sha' do
expect(subject.all).to contain_exactly(pipeline)
end
end
context 'when pipelines exist for the branch and merge request' do
let(:source_ref) { 'feature' }
let(:target_ref) { 'master' }
let!(:branch_pipeline) do
create(:ci_pipeline, source: :push, project: project,
ref: source_ref, sha: shas.second)
end
let!(:tag_pipeline) do
create(:ci_pipeline, project: project, ref: source_ref, tag: true)
end
let!(:detached_merge_request_pipeline) do
create(:ci_pipeline, source: :merge_request_event, project: project,
ref: source_ref, sha: shas.second, merge_request: merge_request)
end
let(:merge_request) do
create(:merge_request, source_project: project, source_branch: source_ref,
target_project: project, target_branch: target_ref)
end
let(:project) { create(:project, :repository) }
let(:shas) { project.repository.commits(source_ref, limit: 2).map(&:id) }
before do
allow(merge_request).to receive(:all_commit_shas) { shas }
end
it 'returns merge request pipeline first' do
expect(subject.all).to eq([detached_merge_request_pipeline, branch_pipeline])
end
context 'when there are a branch pipeline and a merge request pipeline' do
let!(:branch_pipeline_2) do
create(:ci_pipeline, source: :push, project: project,
ref: source_ref, sha: shas.first)
end
let!(:detached_merge_request_pipeline_2) do
create(:ci_pipeline, source: :merge_request_event, project: project,
ref: source_ref, sha: shas.first, merge_request: merge_request)
end
it 'returns merge request pipelines first' do
expect(subject.all)
.to eq([detached_merge_request_pipeline_2,
detached_merge_request_pipeline,
branch_pipeline_2,
branch_pipeline])
end
end
context 'when there are multiple merge request pipelines from the same branch' do
let!(:branch_pipeline_2) do
create(:ci_pipeline, source: :push, project: project,
ref: source_ref, sha: shas.first)
end
let!(:detached_merge_request_pipeline_2) do
create(:ci_pipeline, source: :merge_request_event, project: project,
ref: source_ref, sha: shas.first, merge_request: merge_request_2)
end
let(:merge_request_2) do
create(:merge_request, source_project: project, source_branch: source_ref,
target_project: project, target_branch: 'stable')
end
before do
allow(merge_request_2).to receive(:all_commit_shas) { shas }
end
it 'returns only related merge request pipelines' do
expect(subject.all)
.to eq([detached_merge_request_pipeline,
branch_pipeline_2,
branch_pipeline])
expect(described_class.new(merge_request_2).all)
.to eq([detached_merge_request_pipeline_2,
branch_pipeline_2,
branch_pipeline])
end
end
context 'when detached merge request pipeline is run on head ref of the merge request' do
let!(:detached_merge_request_pipeline) do
create(:ci_pipeline, source: :merge_request_event, project: project,
ref: merge_request.ref_path, sha: shas.second, merge_request: merge_request)
end
it 'sets the head ref of the merge request to the pipeline ref' do
expect(detached_merge_request_pipeline.ref).to match(%r{refs/merge-requests/\d+/head})
end
it 'includes the detached merge request pipeline even though the ref is custom path' do
expect(merge_request.all_pipelines).to include(detached_merge_request_pipeline)
end
end
end
end
end
...@@ -1441,183 +1441,6 @@ describe MergeRequest do ...@@ -1441,183 +1441,6 @@ describe MergeRequest do
end end
end end
describe '#all_pipelines' do
shared_examples 'returning pipelines with proper ordering' do
let!(:all_pipelines) do
subject.all_commit_shas.map do |sha|
create(:ci_empty_pipeline,
project: subject.source_project,
sha: sha,
ref: subject.source_branch)
end
end
it 'returns all pipelines' do
expect(subject.all_pipelines).not_to be_empty
expect(subject.all_pipelines).to eq(all_pipelines.reverse)
end
end
context 'with single merge_request_diffs' do
it_behaves_like 'returning pipelines with proper ordering'
end
context 'with multiple irrelevant merge_request_diffs' do
before do
subject.update(target_branch: 'v1.0.0')
end
it_behaves_like 'returning pipelines with proper ordering'
end
context 'with unsaved merge request' do
subject { build(:merge_request) }
let!(:pipeline) do
create(:ci_empty_pipeline,
project: subject.project,
sha: subject.diff_head_sha,
ref: subject.source_branch)
end
it 'returns pipelines from diff_head_sha' do
expect(subject.all_pipelines).to contain_exactly(pipeline)
end
end
context 'when pipelines exist for the branch and merge request' do
let(:source_ref) { 'feature' }
let(:target_ref) { 'master' }
let!(:branch_pipeline) do
create(:ci_pipeline,
source: :push,
project: project,
ref: source_ref,
sha: shas.second)
end
let!(:detached_merge_request_pipeline) do
create(:ci_pipeline,
source: :merge_request_event,
project: project,
ref: source_ref,
sha: shas.second,
merge_request: merge_request)
end
let(:merge_request) do
create(:merge_request,
source_project: project,
source_branch: source_ref,
target_project: project,
target_branch: target_ref)
end
let(:project) { create(:project, :repository) }
let(:shas) { project.repository.commits(source_ref, limit: 2).map(&:id) }
before do
allow(merge_request).to receive(:all_commit_shas) { shas }
end
it 'returns merge request pipeline first' do
expect(merge_request.all_pipelines)
.to eq([detached_merge_request_pipeline,
branch_pipeline])
end
context 'when there are a branch pipeline and a merge request pipeline' do
let!(:branch_pipeline_2) do
create(:ci_pipeline,
source: :push,
project: project,
ref: source_ref,
sha: shas.first)
end
let!(:detached_merge_request_pipeline_2) do
create(:ci_pipeline,
source: :merge_request_event,
project: project,
ref: source_ref,
sha: shas.first,
merge_request: merge_request)
end
it 'returns merge request pipelines first' do
expect(merge_request.all_pipelines)
.to eq([detached_merge_request_pipeline_2,
detached_merge_request_pipeline,
branch_pipeline_2,
branch_pipeline])
end
end
context 'when there are multiple merge request pipelines from the same branch' do
let!(:branch_pipeline_2) do
create(:ci_pipeline,
source: :push,
project: project,
ref: source_ref,
sha: shas.first)
end
let!(:detached_merge_request_pipeline_2) do
create(:ci_pipeline,
source: :merge_request_event,
project: project,
ref: source_ref,
sha: shas.first,
merge_request: merge_request_2)
end
let(:merge_request_2) do
create(:merge_request,
source_project: project,
source_branch: source_ref,
target_project: project,
target_branch: 'stable')
end
before do
allow(merge_request_2).to receive(:all_commit_shas) { shas }
end
it 'returns only related merge request pipelines' do
expect(merge_request.all_pipelines)
.to eq([detached_merge_request_pipeline,
branch_pipeline_2,
branch_pipeline])
expect(merge_request_2.all_pipelines)
.to eq([detached_merge_request_pipeline_2,
branch_pipeline_2,
branch_pipeline])
end
end
context 'when detached merge request pipeline is run on head ref of the merge request' do
let!(:detached_merge_request_pipeline) do
create(:ci_pipeline,
source: :merge_request_event,
project: project,
ref: merge_request.ref_path,
sha: shas.second,
merge_request: merge_request)
end
it 'sets the head ref of the merge request to the pipeline ref' do
expect(detached_merge_request_pipeline.ref).to match(%r{refs/merge-requests/\d+/head})
end
it 'includes the detached merge request pipeline even though the ref is custom path' do
expect(merge_request.all_pipelines).to include(detached_merge_request_pipeline)
end
end
end
end
describe '#update_head_pipeline' do describe '#update_head_pipeline' do
subject { merge_request.update_head_pipeline } subject { merge_request.update_head_pipeline }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment