Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
fd3a95f07a
commit
1808454313
31 changed files with 319 additions and 68 deletions
|
@ -42,7 +42,7 @@ export default class Playable extends Node {
|
|||
},
|
||||
{
|
||||
tag: `${this.mediaType}[src]`,
|
||||
getAttrs: el => ({ src: el.getAttribute('src'), alt: el.dataset.title }),
|
||||
getAttrs: el => ({ src: el.src, alt: el.dataset.title }),
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<script>
|
||||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
import { n__ } from '~/locale';
|
||||
import { isNumber } from 'underscore';
|
||||
|
||||
export default {
|
||||
components: { Icon },
|
||||
|
@ -16,7 +17,7 @@ export default {
|
|||
diffFilesLength: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null,
|
||||
default: 0,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
|
@ -26,6 +27,9 @@ export default {
|
|||
isCompareVersionsHeader() {
|
||||
return Boolean(this.diffFilesLength);
|
||||
},
|
||||
hasDiffFiles() {
|
||||
return isNumber(this.diffFilesLength) && this.diffFilesLength >= 0;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -38,7 +42,7 @@ export default {
|
|||
'd-inline-flex': !isCompareVersionsHeader,
|
||||
}"
|
||||
>
|
||||
<div v-if="diffFilesLength !== null" class="diff-stats-group">
|
||||
<div v-if="hasDiffFiles" class="diff-stats-group">
|
||||
<icon name="doc-code" class="diff-stats-icon text-secondary" />
|
||||
<strong>{{ diffFilesLength }} {{ filesText }}</strong>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
import LengthValidator from '~/pages/sessions/new/length_validator';
|
||||
import NoEmojiValidator from '~/emoji/no_emoji_validator';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
new LengthValidator(); // eslint-disable-line no-new
|
||||
new NoEmojiValidator(); // eslint-disable-line no-new
|
||||
});
|
|
@ -47,6 +47,7 @@
|
|||
}
|
||||
|
||||
.prometheus-graphs-header {
|
||||
.monitor-environment-dropdown-header header,
|
||||
.monitor-dashboard-dropdown-header header {
|
||||
font-size: $gl-font-size;
|
||||
}
|
||||
|
|
|
@ -8,27 +8,26 @@ class Projects::ProjectMembersController < Projects::ApplicationController
|
|||
# Authorize
|
||||
before_action :authorize_admin_project_member!, except: [:index, :leave, :request_access]
|
||||
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
def index
|
||||
@sort = params[:sort].presence || sort_value_name
|
||||
|
||||
@skip_groups = @project.invited_group_ids
|
||||
@skip_groups += @project.group.self_and_ancestors_ids if @project.group
|
||||
|
||||
@group_links = @project.project_group_links
|
||||
@group_links = @group_links.search(params[:search]) if params[:search].present?
|
||||
|
||||
@skip_groups = @group_links.pluck(:group_id)
|
||||
@skip_groups << @project.namespace_id unless @project.personal?
|
||||
@skip_groups += @project.group.ancestors.pluck(:id) if @project.group
|
||||
@project_members = MembersFinder.new(@project, current_user)
|
||||
.execute(include_relations: requested_relations, params: params.merge(sort: @sort))
|
||||
|
||||
@project_members = MembersFinder.new(@project, current_user).execute(include_relations: requested_relations)
|
||||
@project_members = present_members(@project_members.page(params[:page]))
|
||||
|
||||
if params[:search].present?
|
||||
@project_members = @project_members.joins(:user).merge(User.search(params[:search]))
|
||||
@group_links = @group_links.where(group_id: @project.invited_groups.search(params[:search]).select(:id))
|
||||
end
|
||||
@requesters = present_members(
|
||||
AccessRequestsFinder.new(@project).execute(current_user)
|
||||
)
|
||||
|
||||
@project_members = present_members(@project_members.sort_by_attribute(@sort).page(params[:page]))
|
||||
@requesters = present_members(AccessRequestsFinder.new(@project).execute(current_user))
|
||||
@project_member = @project.project_members.new
|
||||
end
|
||||
# rubocop: enable CodeReuse/ActiveRecord
|
||||
|
||||
def import
|
||||
@projects = current_user.authorized_projects.order_id_desc
|
||||
|
|
|
@ -56,7 +56,6 @@ class RegistrationsController < Devise::RegistrationsController
|
|||
return redirect_to stored_location_or_dashboard_or_almost_there_path(current_user) if current_user.role.present? && !current_user.setup_for_company.nil?
|
||||
|
||||
current_user.name = nil if current_user.name == current_user.username
|
||||
render layout: 'devise_experimental_separate_sign_up_flow'
|
||||
end
|
||||
|
||||
def update_registration
|
||||
|
@ -68,7 +67,7 @@ class RegistrationsController < Devise::RegistrationsController
|
|||
set_flash_message! :notice, :signed_up
|
||||
redirect_to stored_location_or_dashboard_or_almost_there_path(current_user)
|
||||
else
|
||||
render :welcome, layout: 'devise_experimental_separate_sign_up_flow'
|
||||
render :welcome
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class MembersFinder
|
||||
attr_reader :project, :current_user, :group
|
||||
# Params can be any of the following:
|
||||
# sort: string
|
||||
# search: string
|
||||
|
||||
def initialize(project, current_user)
|
||||
@project = project
|
||||
|
@ -9,21 +11,10 @@ class MembersFinder
|
|||
@group = project.group
|
||||
end
|
||||
|
||||
def execute(include_relations: [:inherited, :direct])
|
||||
project_members = project.project_members
|
||||
project_members = project_members.non_invite unless can?(current_user, :admin_project, project)
|
||||
def execute(include_relations: [:inherited, :direct], params: {})
|
||||
members = find_members(include_relations, params)
|
||||
|
||||
return project_members if include_relations == [:direct]
|
||||
|
||||
union_members = group_union_members(include_relations)
|
||||
|
||||
union_members << project_members if include_relations.include?(:direct)
|
||||
|
||||
if union_members.any?
|
||||
distinct_union_of_members(union_members)
|
||||
else
|
||||
project_members
|
||||
end
|
||||
filter_members(members, params)
|
||||
end
|
||||
|
||||
def can?(*args)
|
||||
|
@ -32,6 +23,28 @@ class MembersFinder
|
|||
|
||||
private
|
||||
|
||||
attr_reader :project, :current_user, :group
|
||||
|
||||
def find_members(include_relations, params)
|
||||
project_members = project.project_members
|
||||
project_members = project_members.non_invite unless can?(current_user, :admin_project, project)
|
||||
|
||||
return project_members if include_relations == [:direct]
|
||||
|
||||
union_members = group_union_members(include_relations)
|
||||
union_members << project_members if include_relations.include?(:direct)
|
||||
|
||||
return project_members unless union_members.any?
|
||||
|
||||
distinct_union_of_members(union_members)
|
||||
end
|
||||
|
||||
def filter_members(members, params)
|
||||
members = members.search(params[:search]) if params[:search].present?
|
||||
members = members.sort_by_attribute(params[:sort]) if params[:sort].present?
|
||||
members
|
||||
end
|
||||
|
||||
def group_union_members(include_relations)
|
||||
[].tap do |members|
|
||||
members << direct_group_members(include_relations.include?(:descendants)) if group
|
||||
|
|
|
@ -18,7 +18,7 @@ module CommitsHelper
|
|||
end
|
||||
|
||||
def commit_to_html(commit, ref, project)
|
||||
render 'projects/commits/commit',
|
||||
render 'projects/commits/commit.html',
|
||||
commit: commit,
|
||||
ref: ref,
|
||||
project: project
|
||||
|
|
|
@ -40,7 +40,7 @@ module DiscussionOnDiff
|
|||
# Returns an array of at most 16 highlighted lines above a diff note
|
||||
def truncated_diff_lines(highlight: true, diff_limit: nil)
|
||||
return [] unless on_text?
|
||||
return [] if diff_line.nil? && first_note.is_a?(LegacyDiffNote)
|
||||
return [] if diff_line.nil?
|
||||
|
||||
diff_limit = [diff_limit, NUMBER_OF_TRUNCATED_DIFF_LINES].compact.min
|
||||
lines = highlight ? highlighted_diff_lines : diff_lines
|
||||
|
|
|
@ -31,6 +31,10 @@ class ProjectGroupLink < ApplicationRecord
|
|||
DEVELOPER
|
||||
end
|
||||
|
||||
def self.search(query)
|
||||
joins(:group).merge(Group.search(query))
|
||||
end
|
||||
|
||||
def human_access
|
||||
self.class.access_options.key(self.group_access)
|
||||
end
|
||||
|
|
|
@ -12,7 +12,9 @@ module Projects
|
|||
service = Projects::HousekeepingService.new(@project)
|
||||
|
||||
service.execute do
|
||||
repository.delete_all_refs_except(RESERVED_REF_PREFIXES)
|
||||
import_failure_service.with_retry(action: 'delete_all_refs') do
|
||||
repository.delete_all_refs_except(RESERVED_REF_PREFIXES)
|
||||
end
|
||||
end
|
||||
|
||||
# Right now we don't actually have a way to know if a project
|
||||
|
@ -26,6 +28,10 @@ module Projects
|
|||
|
||||
private
|
||||
|
||||
def import_failure_service
|
||||
@import_failure_service ||= Gitlab::ImportExport::ImportFailureService.new(@project)
|
||||
end
|
||||
|
||||
def repository
|
||||
@repository ||= @project.repository
|
||||
end
|
||||
|
|
|
@ -96,7 +96,7 @@ module Suggestions
|
|||
end
|
||||
|
||||
def suggestion_commit_message(project)
|
||||
project.suggestion_commit_message || DEFAULT_SUGGESTION_COMMIT_MESSAGE
|
||||
project.suggestion_commit_message.presence || DEFAULT_SUGGESTION_COMMIT_MESSAGE
|
||||
end
|
||||
|
||||
def processed_suggestion_commit_message(suggestion)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Support require_password_to_approve in project merge request approvals API
|
||||
merge_request: 24016
|
||||
author:
|
||||
type: added
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix Merge Request comments when some notes are corrupt
|
||||
merge_request: 23786
|
||||
author:
|
||||
type: fixed
|
5
changelogs/unreleased/display-ops-ff-iid.yml
Normal file
5
changelogs/unreleased/display-ops-ff-iid.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Display operations feature flag internal ids
|
||||
merge_request: 23914
|
||||
author:
|
||||
type: added
|
5
changelogs/unreleased/fix-nan-no-diff.yml
Normal file
5
changelogs/unreleased/fix-nan-no-diff.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix showing 'NaN files' when a MR diff does not have any changes
|
||||
merge_request: 24002
|
||||
author:
|
||||
type: fixed
|
5
changelogs/unreleased/id-fix-suggestions.yml
Normal file
5
changelogs/unreleased/id-fix-suggestions.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix applying the suggestions with an empty custom message
|
||||
merge_request: 24144
|
||||
author:
|
||||
type: fixed
|
|
@ -25,7 +25,10 @@ GET /projects/:id/approvals
|
|||
{
|
||||
"approvals_before_merge": 2,
|
||||
"reset_approvals_on_push": true,
|
||||
"disable_overriding_approvers_per_merge_request": false
|
||||
"disable_overriding_approvers_per_merge_request": false,
|
||||
"merge_requests_author_approval": true,
|
||||
"merge_requests_disable_committers_approval": false,
|
||||
"require_password_to_approve": true
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -50,6 +53,7 @@ POST /projects/:id/approvals
|
|||
| `disable_overriding_approvers_per_merge_request` | boolean | no | Allow/Disallow overriding approvers per MR |
|
||||
| `merge_requests_author_approval` | boolean | no | Allow/Disallow authors from self approving merge requests; `true` means authors cannot self approve |
|
||||
| `merge_requests_disable_committers_approval` | boolean | no | Allow/Disallow committers from self approving merge requests |
|
||||
| `require_password_to_approve` | boolean | no | Require approver to enter a password in order to authenticate before adding the approval |
|
||||
|
||||
```json
|
||||
{
|
||||
|
@ -57,7 +61,8 @@ POST /projects/:id/approvals
|
|||
"reset_approvals_on_push": true,
|
||||
"disable_overriding_approvers_per_merge_request": false,
|
||||
"merge_requests_author_approval": false,
|
||||
"merge_requests_disable_committers_approval": false
|
||||
"merge_requests_disable_committers_approval": false,
|
||||
"require_password_to_approve": true
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -441,7 +446,10 @@ PUT /projects/:id/approvers
|
|||
],
|
||||
"approvals_before_merge": 2,
|
||||
"reset_approvals_on_push": true,
|
||||
"disable_overriding_approvers_per_merge_request": false
|
||||
"disable_overriding_approvers_per_merge_request": false,
|
||||
"merge_requests_author_approval": true,
|
||||
"merge_requests_disable_committers_approval": false,
|
||||
"require_password_to_approve": true
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ module Gitlab
|
|||
matches << :console if console?
|
||||
matches << :sidekiq if sidekiq?
|
||||
matches << :rake if rake?
|
||||
matches << :rspec if rspec?
|
||||
matches << :test_suite if test_suite?
|
||||
|
||||
if matches.one?
|
||||
matches.first
|
||||
|
@ -48,8 +48,8 @@ module Gitlab
|
|||
!!(defined?(::Rake) && Rake.application.top_level_tasks.any?)
|
||||
end
|
||||
|
||||
def rspec?
|
||||
Rails.env.test? && process_name == 'rspec'
|
||||
def test_suite?
|
||||
Rails.env.test?
|
||||
end
|
||||
|
||||
def console?
|
||||
|
@ -64,10 +64,6 @@ module Gitlab
|
|||
puma? || sidekiq?
|
||||
end
|
||||
|
||||
def process_name
|
||||
File.basename($0)
|
||||
end
|
||||
|
||||
def max_threads
|
||||
if puma?
|
||||
Puma.cli_config.options[:max_threads]
|
||||
|
|
|
@ -10258,6 +10258,9 @@ msgstr ""
|
|||
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
|
||||
msgstr ""
|
||||
|
||||
msgid "In order to personalize your experience with GitLab<br>we would like to know a bit more about you."
|
||||
msgstr ""
|
||||
|
||||
msgid "In order to tailor your experience with GitLab we<br>would like to know a bit more about you."
|
||||
msgstr ""
|
||||
|
||||
|
@ -10806,6 +10809,9 @@ msgstr ""
|
|||
msgid "June"
|
||||
msgstr ""
|
||||
|
||||
msgid "Just me"
|
||||
msgstr ""
|
||||
|
||||
msgid "Key"
|
||||
msgstr ""
|
||||
|
||||
|
@ -12290,6 +12296,9 @@ msgstr ""
|
|||
msgid "Multiple uploaders found: %{uploader_types}"
|
||||
msgstr ""
|
||||
|
||||
msgid "My company or team"
|
||||
msgstr ""
|
||||
|
||||
msgid "My-Reaction"
|
||||
msgstr ""
|
||||
|
||||
|
@ -19484,6 +19493,9 @@ msgstr ""
|
|||
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
|
||||
msgstr ""
|
||||
|
||||
msgid "This will help us personalize your onboarding experience."
|
||||
msgstr ""
|
||||
|
||||
msgid "This will redirect you to an external sign in page."
|
||||
msgstr ""
|
||||
|
||||
|
@ -21278,6 +21290,9 @@ msgstr ""
|
|||
msgid "Welcome to GitLab, %{first_name}!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Welcome to GitLab.com<br>@%{name}!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Welcome to the Guided GitLab Tour"
|
||||
msgstr ""
|
||||
|
||||
|
@ -21337,6 +21352,9 @@ msgstr ""
|
|||
msgid "Who will be able to see this group?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Who will be using this GitLab subscription?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Wiki"
|
||||
msgstr ""
|
||||
|
||||
|
@ -22051,6 +22069,9 @@ msgstr ""
|
|||
msgid "Your password reset token has expired."
|
||||
msgstr ""
|
||||
|
||||
msgid "Your profile"
|
||||
msgstr ""
|
||||
|
||||
msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -415,4 +415,36 @@ describe RegistrationsController do
|
|||
patch :update_registration, params: { user: { role: 'software_developer', setup_for_company: 'false' } }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#welcome' do
|
||||
subject { get :welcome }
|
||||
|
||||
before do
|
||||
sign_in(create(:user))
|
||||
end
|
||||
|
||||
context 'signup_flow experiment enabled' do
|
||||
before do
|
||||
stub_experiment_for_user(signup_flow: true)
|
||||
end
|
||||
|
||||
it 'renders the devise_experimental_separate_sign_up_flow layout' do
|
||||
expected_layout = Gitlab.ee? ? :checkout : :devise_experimental_separate_sign_up_flow
|
||||
|
||||
expect(subject).to render_template(expected_layout)
|
||||
end
|
||||
end
|
||||
|
||||
context 'signup_flow experiment disabled' do
|
||||
before do
|
||||
stub_experiment_for_user(signup_flow: false)
|
||||
end
|
||||
|
||||
it 'renders the devise layout' do
|
||||
expected_layout = Gitlab.ee? ? :checkout : :devise
|
||||
|
||||
expect(subject).to render_template(expected_layout)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -172,18 +172,36 @@ describe 'Copy as GFM', :js do
|
|||
'![Image](https://example.com/image.png)'
|
||||
)
|
||||
|
||||
verify_media_with_partial_path(
|
||||
'![Image](/uploads/a123/image.png)',
|
||||
|
||||
project_media_uri(@project, '/uploads/a123/image.png')
|
||||
)
|
||||
|
||||
verify(
|
||||
'VideoLinkFilter',
|
||||
|
||||
'![Video](https://example.com/video.mp4)'
|
||||
)
|
||||
|
||||
verify_media_with_partial_path(
|
||||
'![Video](/uploads/a123/video.mp4)',
|
||||
|
||||
project_media_uri(@project, '/uploads/a123/video.mp4')
|
||||
)
|
||||
|
||||
verify(
|
||||
'AudioLinkFilter',
|
||||
|
||||
'![Audio](https://example.com/audio.wav)'
|
||||
)
|
||||
|
||||
verify_media_with_partial_path(
|
||||
'![Audio](/uploads/a123/audio.wav)',
|
||||
|
||||
project_media_uri(@project, '/uploads/a123/audio.wav')
|
||||
)
|
||||
|
||||
verify(
|
||||
'MathFilter: math as converted from GFM to HTML',
|
||||
|
||||
|
@ -647,6 +665,16 @@ describe 'Copy as GFM', :js do
|
|||
end
|
||||
end
|
||||
|
||||
def project_media_uri(project, media_path)
|
||||
"#{project_path(project)}#{media_path}"
|
||||
end
|
||||
|
||||
def verify_media_with_partial_path(gfm, media_uri)
|
||||
html = gfm_to_html(gfm)
|
||||
output_gfm = html_to_gfm(html)
|
||||
expect(output_gfm).to include(media_uri)
|
||||
end
|
||||
|
||||
# Fake a `current_user` helper
|
||||
def current_user
|
||||
@feat.user
|
||||
|
|
|
@ -445,8 +445,8 @@ end
|
|||
|
||||
describe 'With experimental flow' do
|
||||
before do
|
||||
stub_experiment(signup_flow: true)
|
||||
stub_experiment_for_user(signup_flow: true)
|
||||
stub_experiment(signup_flow: true, paid_signup_flow: false)
|
||||
stub_experiment_for_user(signup_flow: true, paid_signup_flow: false)
|
||||
end
|
||||
|
||||
it_behaves_like 'Signup'
|
||||
|
|
|
@ -75,6 +75,15 @@ describe MembersFinder, '#execute' do
|
|||
expect(result).to contain_exactly(member2, member3)
|
||||
end
|
||||
|
||||
it 'returns only inherited members of a personal project' do
|
||||
project = create(:project, namespace: user1.namespace)
|
||||
member = project.members.first
|
||||
|
||||
result = described_class.new(project, user1).execute(include_relations: [:inherited])
|
||||
|
||||
expect(result).to contain_exactly(member)
|
||||
end
|
||||
|
||||
it 'returns the members.access_level when the user is invited', :nested_groups do
|
||||
member_invite = create(:project_member, :invited, project: project, invite_email: create(:user).email)
|
||||
member1 = group.add_maintainer(user2)
|
||||
|
@ -96,6 +105,26 @@ describe MembersFinder, '#execute' do
|
|||
expect(result.first.access_level).to eq(Gitlab::Access::DEVELOPER)
|
||||
end
|
||||
|
||||
it 'returns searched members if requested' do
|
||||
project.add_maintainer(user2)
|
||||
project.add_maintainer(user3)
|
||||
member3 = project.add_maintainer(user4)
|
||||
|
||||
result = described_class.new(project, user2).execute(params: { search: user4.name })
|
||||
|
||||
expect(result).to contain_exactly(member3)
|
||||
end
|
||||
|
||||
it 'returns members sorted by id_desc' do
|
||||
member1 = project.add_maintainer(user2)
|
||||
member2 = project.add_maintainer(user3)
|
||||
member3 = project.add_maintainer(user4)
|
||||
|
||||
result = described_class.new(project, user2).execute(params: { sort: 'id_desc' })
|
||||
|
||||
expect(result).to eq([member3, member2, member1])
|
||||
end
|
||||
|
||||
context 'when include_invited_groups_members == true' do
|
||||
subject { described_class.new(project, user2).execute(include_relations: [:inherited, :direct, :invited_groups_members]) }
|
||||
|
||||
|
|
|
@ -3,11 +3,12 @@ import Icon from '~/vue_shared/components/icon.vue';
|
|||
import DiffStats from '~/diffs/components/diff_stats.vue';
|
||||
|
||||
describe('diff_stats', () => {
|
||||
it('does not render a group if diffFileLengths is not passed in', () => {
|
||||
it('does not render a group if diffFileLengths is not a number', () => {
|
||||
const wrapper = shallowMount(DiffStats, {
|
||||
propsData: {
|
||||
addedLines: 1,
|
||||
removedLines: 2,
|
||||
diffFilesLength: Number.NaN,
|
||||
},
|
||||
});
|
||||
const groups = wrapper.findAll('.diff-stats-group');
|
||||
|
|
|
@ -69,4 +69,17 @@ describe CommitsHelper do
|
|||
expect(node[:href]).to eq('http://example.com/file.html')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#commit_to_html' do
|
||||
let(:project) { create(:project, :repository) }
|
||||
let(:ref) { 'master' }
|
||||
let(:commit) { project.commit(ref) }
|
||||
|
||||
it 'renders HTML representation of a commit' do
|
||||
assign(:project, project)
|
||||
allow(helper).to receive(:current_user).and_return(project.owner)
|
||||
|
||||
expect(helper.commit_to_html(commit, ref, project)).to include('<div class="commit-content')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,6 +5,7 @@ require 'spec_helper'
|
|||
describe Gitlab::Runtime do
|
||||
before do
|
||||
allow(described_class).to receive(:process_name).and_return('ruby')
|
||||
stub_rails_env('production')
|
||||
end
|
||||
|
||||
context "when unknown" do
|
||||
|
@ -47,7 +48,7 @@ describe Gitlab::Runtime do
|
|||
expect(subject.sidekiq?).to be(false)
|
||||
expect(subject.console?).to be(false)
|
||||
expect(subject.rake?).to be(false)
|
||||
expect(subject.rspec?).to be(false)
|
||||
expect(subject.test_suite?).to be(false)
|
||||
end
|
||||
|
||||
it "reports its maximum concurrency" do
|
||||
|
@ -74,7 +75,7 @@ describe Gitlab::Runtime do
|
|||
expect(subject.sidekiq?).to be(false)
|
||||
expect(subject.console?).to be(false)
|
||||
expect(subject.rake?).to be(false)
|
||||
expect(subject.rspec?).to be(false)
|
||||
expect(subject.test_suite?).to be(false)
|
||||
end
|
||||
|
||||
it "reports its maximum concurrency" do
|
||||
|
@ -106,7 +107,7 @@ describe Gitlab::Runtime do
|
|||
expect(subject.puma?).to be(false)
|
||||
expect(subject.console?).to be(false)
|
||||
expect(subject.rake?).to be(false)
|
||||
expect(subject.rspec?).to be(false)
|
||||
expect(subject.test_suite?).to be(false)
|
||||
end
|
||||
|
||||
it "reports its maximum concurrency" do
|
||||
|
@ -131,7 +132,7 @@ describe Gitlab::Runtime do
|
|||
expect(subject.sidekiq?).to be(false)
|
||||
expect(subject.puma?).to be(false)
|
||||
expect(subject.rake?).to be(false)
|
||||
expect(subject.rspec?).to be(false)
|
||||
expect(subject.test_suite?).to be(false)
|
||||
end
|
||||
|
||||
it "reports its maximum concurrency" do
|
||||
|
@ -139,14 +140,14 @@ describe Gitlab::Runtime do
|
|||
end
|
||||
end
|
||||
|
||||
context "rspec" do
|
||||
context "test suite" do
|
||||
before do
|
||||
allow(described_class).to receive(:process_name).and_return('rspec')
|
||||
stub_rails_env('test')
|
||||
end
|
||||
|
||||
it "identifies itself" do
|
||||
expect(subject.identify).to eq(:rspec)
|
||||
expect(subject.rspec?).to be(true)
|
||||
expect(subject.identify).to eq(:test_suite)
|
||||
expect(subject.test_suite?).to be(true)
|
||||
end
|
||||
|
||||
it "does not identify as others" do
|
||||
|
|
|
@ -59,6 +59,18 @@ describe DiscussionOnDiff do
|
|||
end
|
||||
end
|
||||
|
||||
context "when the diff line does not exist on a corrupt diff note" do
|
||||
subject { create(:diff_note_on_merge_request, line_number: 18).to_discussion }
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:diff_line) { nil }
|
||||
end
|
||||
|
||||
it "returns an empty array" do
|
||||
expect(truncated_lines).to eq([])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the discussion is on an image' do
|
||||
subject { create(:image_diff_note_on_merge_request).to_discussion }
|
||||
|
||||
|
|
|
@ -47,4 +47,12 @@ describe ProjectGroupLink do
|
|||
group_users.each { |user| expect(user.authorized_projects).not_to include(project) }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'search by group name' do
|
||||
let_it_be(:project_group_link) { create(:project_group_link) }
|
||||
let_it_be(:group) { project_group_link.group }
|
||||
|
||||
it { expect(described_class.search(group.name)).to eq([project_group_link]) }
|
||||
it { expect(described_class.search('not-a-group-name')).to be_empty }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,7 +20,7 @@ describe Projects::AfterImportService do
|
|||
allow(housekeeping_service)
|
||||
.to receive(:execute).and_yield
|
||||
|
||||
expect(housekeeping_service).to receive(:increment!)
|
||||
allow(housekeeping_service).to receive(:increment!)
|
||||
end
|
||||
|
||||
it 'performs housekeeping' do
|
||||
|
@ -58,6 +58,52 @@ describe Projects::AfterImportService do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when after import action throw non-retriable exception' do
|
||||
let(:exception) { StandardError.new('after import error') }
|
||||
|
||||
before do
|
||||
allow(repository)
|
||||
.to receive(:delete_all_refs_except)
|
||||
.and_raise(exception)
|
||||
end
|
||||
|
||||
it 'throws after import error' do
|
||||
expect { subject.execute }.to raise_exception('after import error')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when after import action throw retriable exception one time' do
|
||||
let(:exception) { GRPC::DeadlineExceeded.new }
|
||||
|
||||
before do
|
||||
call_count = 0
|
||||
|
||||
allow(repository).to receive(:delete_all_refs_except).and_wrap_original do |original_method, *args|
|
||||
call_count += 1
|
||||
call_count > 1 ? original_method.call(*args) : raise(exception)
|
||||
end
|
||||
|
||||
subject.execute
|
||||
end
|
||||
|
||||
it 'removes refs/pull/**/*' do
|
||||
expect(rugged.references.map(&:name))
|
||||
.not_to include(%r{\Arefs/pull/})
|
||||
end
|
||||
|
||||
it 'records the failures in the database', :aggregate_failures do
|
||||
import_failure = ImportFailure.last
|
||||
|
||||
expect(import_failure.source).to eq('delete_all_refs')
|
||||
expect(import_failure.project_id).to eq(project.id)
|
||||
expect(import_failure.relation_key).to be_nil
|
||||
expect(import_failure.relation_index).to be_nil
|
||||
expect(import_failure.exception_class).to eq('GRPC::DeadlineExceeded')
|
||||
expect(import_failure.exception_message).to be_present
|
||||
expect(import_failure.correlation_id_value).not_to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
def rugged
|
||||
rugged_repo(repository)
|
||||
end
|
||||
|
|
|
@ -57,10 +57,22 @@ describe Suggestions::ApplyService do
|
|||
end
|
||||
|
||||
context 'is not specified' do
|
||||
let(:message) { nil }
|
||||
let(:expected_value) { "Apply suggestion to files/ruby/popen.rb" }
|
||||
|
||||
it 'sets default commit message' do
|
||||
expect(project.repository.commit.message).to eq("Apply suggestion to files/ruby/popen.rb")
|
||||
context 'is nil' do
|
||||
let(:message) { nil }
|
||||
|
||||
it 'sets default commit message' do
|
||||
expect(project.repository.commit.message).to eq(expected_value)
|
||||
end
|
||||
end
|
||||
|
||||
context 'is an empty string' do
|
||||
let(:message) { '' }
|
||||
|
||||
it 'sets default commit message' do
|
||||
expect(project.repository.commit.message).to eq(expected_value)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue