Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-10-21 06:09:17 +00:00
parent 005a5fa8a9
commit 5f80f7a4bf
17 changed files with 106 additions and 210 deletions

View File

@ -2,7 +2,7 @@
/* eslint-disable vue/no-v-html */ /* eslint-disable vue/no-v-html */
import { mapActions, mapState } from 'vuex'; import { mapActions, mapState } from 'vuex';
import { throttle } from 'lodash'; import { throttle } from 'lodash';
import { GlIcon, GlTooltipDirective } from '@gitlab/ui'; import { GlTooltipDirective, GlButton, GlIcon } from '@gitlab/ui';
import { __ } from '../../../locale'; import { __ } from '../../../locale';
import ScrollButton from './detail/scroll_button.vue'; import ScrollButton from './detail/scroll_button.vue';
import JobDescription from './detail/description.vue'; import JobDescription from './detail/description.vue';
@ -17,6 +17,7 @@ export default {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
components: { components: {
GlButton,
GlIcon, GlIcon,
ScrollButton, ScrollButton,
JobDescription, JobDescription,
@ -75,9 +76,9 @@ export default {
<template> <template>
<div class="ide-pipeline build-page d-flex flex-column flex-fill"> <div class="ide-pipeline build-page d-flex flex-column flex-fill">
<header class="ide-job-header d-flex align-items-center"> <header class="ide-job-header d-flex align-items-center">
<button class="btn btn-default btn-sm d-flex" @click="setDetailJob(null)"> <gl-button category="secondary" icon="chevron-left" size="small" @click="setDetailJob(null)">
<gl-icon name="chevron-left" /> {{ __('View jobs') }} {{ __('View jobs') }}
</button> </gl-button>
</header> </header>
<div class="top-bar d-flex border-left-0 mr-3"> <div class="top-bar d-flex border-left-0 mr-3">
<job-description :job="detailJob" /> <job-description :job="detailJob" />

View File

@ -1,9 +1,11 @@
<script> <script>
import { GlButton } from '@gitlab/ui';
import JobDescription from './detail/description.vue'; import JobDescription from './detail/description.vue';
export default { export default {
components: { components: {
JobDescription, JobDescription,
GlButton,
}, },
props: { props: {
job: { job: {
@ -28,9 +30,9 @@ export default {
<div class="ide-job-item"> <div class="ide-job-item">
<job-description :job="job" class="gl-mr-3" /> <job-description :job="job" class="gl-mr-3" />
<div class="ml-auto align-self-center"> <div class="ml-auto align-self-center">
<button v-if="job.started" type="button" class="btn btn-default btn-sm" @click="clickViewLog"> <gl-button v-if="job.started" category="secondary" size="small" @click="clickViewLog">
{{ __('View log') }} {{ __('View log') }}
</button> </gl-button>
</div> </div>
</div> </div>
</template> </template>

View File

@ -1,9 +1,8 @@
<script> <script>
import { GlIcon } from '@gitlab/ui'; import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { __ } from '~/locale'; import { __ } from '~/locale';
import Tracking from '~/tracking'; import Tracking from '~/tracking';
import toggleButton from '~/vue_shared/components/toggle_button.vue'; import toggleButton from '~/vue_shared/components/toggle_button.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
const ICON_ON = 'notifications'; const ICON_ON = 'notifications';
@ -13,7 +12,7 @@ const LABEL_OFF = __('Notifications off');
export default { export default {
directives: { directives: {
tooltip, GlTooltip: GlTooltipDirective,
}, },
components: { components: {
GlIcon, GlIcon,
@ -110,12 +109,9 @@ export default {
<div> <div>
<span <span
ref="tooltip" ref="tooltip"
v-tooltip v-gl-tooltip.viewport.left
class="sidebar-collapsed-icon"
:title="notificationTooltip" :title="notificationTooltip"
data-container="body" class="sidebar-collapsed-icon"
data-placement="left"
data-boundary="viewport"
@click="onClickCollapsedIcon" @click="onClickCollapsedIcon"
> >
<gl-icon <gl-icon

View File

@ -252,15 +252,6 @@
} }
} }
.split-one {
display: inline-table;
margin-right: 12px;
> a {
margin: -1px;
}
}
.save-project-loader { .save-project-loader {
margin-top: 50px; margin-top: 50px;
margin-bottom: 50px; margin-bottom: 50px;
@ -505,92 +496,6 @@
} }
} }
.create-project-options {
display: flex;
@include media-breakpoint-down(xs) {
display: block;
}
.first-column {
@include media-breakpoint-up(xs) {
max-width: 50%;
padding-right: 30px;
}
@include media-breakpoint-down(xs) {
max-width: 100%;
width: 100%;
}
}
.second-column {
@include media-breakpoint-up(xs) {
width: 50%;
flex: 1;
padding-left: 30px;
position: relative;
}
@include media-breakpoint-down(xs) {
max-width: 100%;
width: 100%;
padding-left: 0;
position: relative;
}
// Mobile
@include media-breakpoint-down(xs) {
padding-top: 30px;
}
&::before {
content: 'OR';
position: absolute;
left: -10px;
top: 50%;
z-index: 10;
padding: $gl-padding-8 0;
text-align: center;
background-color: $white;
color: $gl-text-color-tertiary;
transform: translateY(-50%);
font-size: 12px;
font-weight: $gl-font-weight-bold;
line-height: 20px;
// Mobile
@include media-breakpoint-down(xs) {
left: 50%;
top: 0;
transform: translateX(-50%);
padding: 0 $gl-padding-8;
}
}
&::after {
content: '';
position: absolute;
background-color: $border-color;
bottom: 0;
left: 0;
right: auto;
height: 100%;
width: 1px;
top: 0;
// Mobile
@include media-breakpoint-down(xs) {
top: 10px;
left: 10px;
right: 10px;
height: 1px;
width: auto;
}
}
}
}
.project-stats, .project-stats,
.project-buttons { .project-buttons {
.scrolling-tabs-container { .scrolling-tabs-container {
@ -754,17 +659,6 @@ pre.light-well {
} }
} }
.project-footer {
margin-top: 20px;
.btn-remove {
@include btn-middle;
@include btn-red;
float: left !important;
}
}
/* /*
* Projects list rendered on dashboard and user page * Projects list rendered on dashboard and user page
*/ */
@ -1059,24 +953,6 @@ pre.light-well {
} }
} }
.cannot-be-merged,
.cannot-be-merged:hover {
color: $red-500;
margin-top: 2px;
position: relative;
z-index: 2;
}
.private-forks-notice .private-fork-icon {
i:nth-child(1) {
color: $green-600;
}
i:nth-child(2) {
color: $white;
}
}
.new-protected-branch, .new-protected-branch,
.new-protected-tag { .new-protected-tag {
label { label {
@ -1233,34 +1109,6 @@ pre.light-well {
} }
} }
.variables-table {
table-layout: fixed;
&.table-responsive {
border: 0;
}
.variable-key {
max-width: 120px;
overflow: hidden;
word-wrap: break-word;
white-space: nowrap;
text-overflow: ellipsis;
}
.variable-value {
max-width: 150px;
overflow: hidden;
word-wrap: break-word;
white-space: nowrap;
text-overflow: ellipsis;
}
.variable-menu {
text-align: right;
}
}
.services-installation-info .row { .services-installation-info .row {
margin-bottom: 10px; margin-bottom: 10px;
} }
@ -1286,18 +1134,6 @@ pre.light-well {
padding-bottom: 37px; padding-bottom: 37px;
} }
.project-ci-body {
.incorrect-syntax {
font-size: 18px;
color: $red-500;
}
.correct-syntax {
font-size: 18px;
color: $green-500;
}
}
.project-ci-linter { .project-ci-linter {
.ci-editor { .ci-editor {
height: 400px; height: 400px;

View File

@ -1,7 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
module DeferScriptTagHelper module DeferScriptTagHelper
# Override the default ActionView `javascript_include_tag` helper to support page specific deferred loading # Override the default ActionView `javascript_include_tag` helper to support page specific deferred loading.
# PLEASE NOTE: `defer` is also critical so that we don't run JavaScript entrypoints before the DOM is ready.
# Please see https://gitlab.com/groups/gitlab-org/-/epics/4538#note_432159769.
def javascript_include_tag(*sources) def javascript_include_tag(*sources)
super(*sources, defer: true) super(*sources, defer: true)
end end

View File

@ -2090,21 +2090,36 @@ class Project < ApplicationRecord
(auto_devops || build_auto_devops)&.predefined_variables (auto_devops || build_auto_devops)&.predefined_variables
end end
# Tries to set repository as read_only, checking for existing Git transfers in progress beforehand RepositoryReadOnlyError = Class.new(StandardError)
# Tries to set repository as read_only, checking for existing Git transfers in
# progress beforehand. Setting a repository read-only will fail if it is
# already in that state.
# #
# @return [Boolean] true when set to read_only or false when an existing git transfer is in progress # @return nil. Failures will raise an exception
def set_repository_read_only! def set_repository_read_only!
with_lock do with_lock do
break false if git_transfer_in_progress? raise RepositoryReadOnlyError, _('Git transfer in progress') if
git_transfer_in_progress?
update_column(:repository_read_only, true) raise RepositoryReadOnlyError, _('Repository already read-only') if
self.class.where(id: id).pick(:repository_read_only)
raise ActiveRecord::RecordNotSaved, _('Database update failed') unless
update_column(:repository_read_only, true)
nil
end end
end end
# Set repository as writable again # Set repository as writable again. Unlike setting it read-only, this will
# succeed if the repository is already writable.
def set_repository_writable! def set_repository_writable!
with_lock do with_lock do
update_column(:repository_read_only, false) raise ActiveRecord::RecordNotSaved, _('Database update failed') unless
update_column(:repository_read_only, false)
nil
end end
end end

View File

@ -46,8 +46,15 @@ class ProjectRepositoryStorageMove < ApplicationRecord
transition replicated: :cleanup_failed transition replicated: :cleanup_failed
end end
after_transition initial: :scheduled do |storage_move| around_transition initial: :scheduled do |storage_move, block|
storage_move.project.update_column(:repository_read_only, true) block.call
begin
storage_move.project.set_repository_read_only!
rescue => err
errors.add(:project, err.message)
next false
end
storage_move.run_after_commit do storage_move.run_after_commit do
ProjectUpdateRepositoryStorageWorker.perform_async( ProjectUpdateRepositoryStorageWorker.perform_async(
@ -56,17 +63,18 @@ class ProjectRepositoryStorageMove < ApplicationRecord
storage_move.id storage_move.id
) )
end end
true
end end
after_transition started: :replicated do |storage_move| before_transition started: :replicated do |storage_move|
storage_move.project.update_columns( storage_move.project.set_repository_writable!
repository_read_only: false,
repository_storage: storage_move.destination_storage_name storage_move.project.update_column(:repository_storage, storage_move.destination_storage_name)
)
end end
after_transition started: :failed do |storage_move| before_transition started: :failed do |storage_move|
storage_move.project.update_column(:repository_read_only, false) storage_move.project.set_repository_writable!
end end
state :initial, value: 1 state :initial, value: 1

View File

@ -79,13 +79,12 @@ module Projects
end end
def try_to_set_repository_read_only! def try_to_set_repository_read_only!
# Mitigate any push operation to start during migration project.set_repository_read_only!
unless project.set_repository_read_only! rescue Project::RepositoryReadOnlyError => err
migration_error = "Target repository '#{old_disk_path}' cannot be made read-only as there is a git transfer in progress" migration_error = "Target repository '#{old_disk_path}' cannot be made read-only: #{err.message}"
logger.error migration_error logger.error migration_error
raise RepositoryInUseError, migration_error raise RepositoryInUseError, migration_error
end
end end
def wiki_path_suffix def wiki_path_suffix

View File

@ -21,8 +21,10 @@ module Projects
project.storage_version = nil project.storage_version = nil
end end
project.repository_read_only = false project.transaction do
project.save!(validate: false) project.save!(validate: false)
project.set_repository_writable!
end
if result && block_given? if result && block_given?
yield yield

View File

@ -15,9 +15,8 @@
%script#js-board-modal-filter{ type: "text/x-template" }= render "shared/issuable/search_bar", type: :boards_modal, show_sorting_dropdown: false %script#js-board-modal-filter{ type: "text/x-template" }= render "shared/issuable/search_bar", type: :boards_modal, show_sorting_dropdown: false
%script#js-board-promotion{ type: "text/x-template" }= render_if_exists "shared/promotions/promote_issue_board" %script#js-board-promotion{ type: "text/x-template" }= render_if_exists "shared/promotions/promote_issue_board"
= render 'shared/issuable/search_bar', type: :boards, board: board
#board-app.boards-app.position-relative{ "v-cloak" => "true", data: board_data, ":class" => "{ 'is-compact': detailIssueVisible }" } #board-app.boards-app.position-relative{ "v-cloak" => "true", data: board_data, ":class" => "{ 'is-compact': detailIssueVisible }" }
= render 'shared/issuable/search_bar', type: :boards, board: board
- if Feature.enabled?(:boards_with_swimlanes, current_board_parent) || Feature.enabled?(:graphql_board_lists, current_board_parent) - if Feature.enabled?(:boards_with_swimlanes, current_board_parent) || Feature.enabled?(:graphql_board_lists, current_board_parent)
%board-content{ "v-cloak" => "true", %board-content{ "v-cloak" => "true",
"ref" => "board_content", "ref" => "board_content",

View File

@ -0,0 +1,5 @@
---
title: Fix a race condition checking whether a project is read-only
merge_request: 45160
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Migrate collapsed notification tooltip
merge_request: 45453
author: artychan
type: other

View File

@ -566,3 +566,11 @@ Additionally, we provide a dedicated project containing the versioned legacy tem
This can be useful for offline setups or anyone wishing to use [Auto DevOps](../../topics/autodevops/index.md). This can be useful for offline setups or anyone wishing to use [Auto DevOps](../../topics/autodevops/index.md).
Instructions are available in the [legacy template project](https://gitlab.com/gitlab-org/auto-devops-v12-10). Instructions are available in the [legacy template project](https://gitlab.com/gitlab-org/auto-devops-v12-10).
#### Vulnerabilities are found, but the job succeeds. How can I have a pipeline fail instead?
This is the current default behavior, because the job's status indicates success or failure of the analyzer itself.
Analyzer results are displayed in the [job logs](../../ci/pipelines/#expand-and-collapse-job-log-sections),
[Merge Request widget](sast/index.md#overview)
or [Security Dashboard](security_dashboard/index.md).
There is [an open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/235772) in which changes to this behavior are being discussed.

View File

@ -8411,6 +8411,9 @@ msgstr ""
msgid "Data is still calculating..." msgid "Data is still calculating..."
msgstr "" msgstr ""
msgid "Database update failed"
msgstr ""
msgid "Datasource name not found" msgid "Datasource name not found"
msgstr "" msgstr ""
@ -12249,6 +12252,9 @@ msgstr ""
msgid "Git strategy for pipelines" msgid "Git strategy for pipelines"
msgstr "" msgstr ""
msgid "Git transfer in progress"
msgstr ""
msgid "Git version" msgid "Git version"
msgstr "" msgstr ""
@ -22297,6 +22303,9 @@ msgstr ""
msgid "Repository Settings" msgid "Repository Settings"
msgstr "" msgstr ""
msgid "Repository already read-only"
msgstr ""
msgid "Repository check" msgid "Repository check"
msgstr "" msgstr ""

View File

@ -94,7 +94,7 @@ describe('Subscriptions', () => {
it('sets the correct display text', () => { it('sets the correct display text', () => {
expect(wrapper.find('.issuable-header-text').text()).toContain(subscribeDisabledDescription); expect(wrapper.find('.issuable-header-text').text()).toContain(subscribeDisabledDescription);
expect(wrapper.find({ ref: 'tooltip' }).attributes('data-original-title')).toBe( expect(wrapper.find({ ref: 'tooltip' }).attributes('title')).toBe(
subscribeDisabledDescription, subscribeDisabledDescription,
); );
}); });

View File

@ -3003,14 +3003,23 @@ RSpec.describe Project do
describe '#set_repository_read_only!' do describe '#set_repository_read_only!' do
let(:project) { create(:project) } let(:project) { create(:project) }
it 'returns true when there is no existing git transfer in progress' do it 'makes the repository read-only' do
expect(project.set_repository_read_only!).to be_truthy expect { project.set_repository_read_only! }
.to change(project, :repository_read_only?)
.from(false)
.to(true)
end end
it 'returns false when there is an existing git transfer in progress' do it 'raises an error if the project is already read-only' do
project.set_repository_read_only!
expect { project.set_repository_read_only! }.to raise_error(described_class::RepositoryReadOnlyError, /already read-only/)
end
it 'raises an error when there is an existing git transfer in progress' do
allow(project).to receive(:git_transfer_in_progress?) { true } allow(project).to receive(:git_transfer_in_progress?) { true }
expect(project.set_repository_read_only!).to be_falsey expect { project.set_repository_read_only! }.to raise_error(described_class::RepositoryReadOnlyError, /in progress/)
end end
end end

View File

@ -18,7 +18,7 @@ RSpec.describe 'projects/merge_requests/show.html.haml' do
render render
expect(rendered).not_to have_css('.cannot-be-merged') expect(rendered).not_to have_css('.merge-icon')
end end
end end
end end