Commit 1f999262 authored by Shinya Maeda's avatar Shinya Maeda

Merge branch 'master-ce' into artifact-format-v2

parents 8b3c7f57 87f03f01
......@@ -2,6 +2,24 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 11.1.3 (2018-07-27)
### Fixed (8 changes, 1 of them is from the community)
- Rework some projects table indexes around repository_storage field. !20377
- Fix navigation to First and Next discussion on MR Changes tab. !20434
- Fix showing outdated discussions on Changes tab. !20445
- Fix autosave and ESC confirmation issues for MR discussions. !20569
- Fix rendering of the context lines in MR diffs page. !20642
- Don't overflow project/group dropdown results. !20704 (gfyoung)
- Fixed IDE not opening JSON files. !20798
- Disable Gitaly timeouts when creating or restoring backups. !20810
### Performance (1 change)
- Reduces the client side memory footprint on merge requests. !20744
## 11.1.2 (2018-07-26)
### Security (4 changes)
......
......@@ -364,7 +364,7 @@ GEM
grape-entity (0.7.1)
activesupport (>= 4.0)
multi_json (>= 1.3.2)
grape-path-helpers (1.0.5)
grape-path-helpers (1.0.6)
activesupport (>= 4, < 5.1)
grape (~> 1.0)
rake (~> 12)
......@@ -378,7 +378,8 @@ GEM
google-protobuf (~> 3.1)
googleapis-common-protos-types (~> 1.0.0)
googleauth (>= 0.5.1, < 0.7)
haml (4.0.7)
haml (5.0.4)
temple (>= 0.8.0)
tilt
haml_lint (0.26.0)
haml (>= 4.0, < 5.1)
......@@ -400,7 +401,7 @@ GEM
hipchat (1.5.2)
httparty
mimemagic
html-pipeline (2.8.3)
html-pipeline (2.8.4)
activesupport (>= 2)
nokogiri (>= 1.4)
html2text (0.2.0)
......@@ -518,7 +519,7 @@ GEM
net-ssh (5.0.1)
netrc (0.11.0)
nio4r (2.3.1)
nokogiri (1.8.3)
nokogiri (1.8.4)
mini_portile2 (~> 2.3.0)
nokogumbo (1.5.0)
nokogiri
......@@ -821,7 +822,7 @@ GEM
et-orbi (~> 1.0)
rugged (0.27.2)
safe_yaml (1.0.4)
sanitize (4.6.5)
sanitize (4.6.6)
crass (~> 1.0.2)
nokogiri (>= 1.4.4)
nokogumbo (~> 1.4)
......@@ -915,7 +916,7 @@ GEM
rack (>= 1, < 3)
thor (0.19.4)
thread_safe (0.3.6)
tilt (2.0.6)
tilt (2.0.8)
timecop (0.8.1)
timfel-krb5-auth (0.8.3)
toml (0.1.2)
......
......@@ -93,7 +93,7 @@ export default {
<icon
:size="16"
class="prepend-left-8 append-right-8"
name="doc_image"
name="doc-image"
aria-hidden="true"
/>
</div>
......
......@@ -56,7 +56,7 @@ export default {
>
<icon
:size="12"
name="more"
name="ellipsis_h"
/>
</button>
<div class="dropdown-menu dropdown-menu-right">
......
......@@ -14,7 +14,7 @@ import tooltip from '../../../vue_shared/directives/tooltip';
* "id": 4256,
* "name": "test",
* "status": {
* "icon": "icon_status_success",
* "icon": "status_success",
* "text": "passed",
* "label": "passed",
* "group": "success",
......
......@@ -13,7 +13,7 @@ import tooltip from '../../../vue_shared/directives/tooltip';
* "id": 4256,
* "name": "test",
* "status": {
* "icon": "icon_status_success",
* "icon": "status_success",
* "text": "passed",
* "label": "passed",
* "group": "success",
......
......@@ -22,8 +22,8 @@
height: 16px;
background-size: cover;
&.gl-snippet-icon-doc_code { background-position: 0 0; }
&.gl-snippet-icon-doc_text { background-position: 0 -16px; }
&.gl-snippet-icon-doc-code { background-position: 0 0; }
&.gl-snippet-icon-doc-text { background-position: 0 -16px; }
&.gl-snippet-icon-download { background-position: 0 -32px; }
}
......
......@@ -7,7 +7,7 @@ class Admin::ProjectsFinder
end
def execute
items = Project.without_deleted.with_statistics
items = Project.without_deleted.with_statistics.with_route
items = by_namespace_id(items)
items = by_visibilty_level(items)
items = by_with_push(items)
......@@ -16,7 +16,7 @@ class Admin::ProjectsFinder
items = by_archived(items)
items = by_personal(items)
items = by_name(items)
items = items.includes(namespace: [:owner])
items = items.includes(namespace: [:owner, :route])
sort(items).page(params[:page])
end
......
......@@ -116,7 +116,7 @@ module SnippetsHelper
raw_project_snippet_url(@snippet.project, @snippet)
end
link_to external_snippet_icon('doc_code'), snippet_raw_url, class: 'btn', target: '_blank', rel: 'noopener noreferrer', title: 'Open raw'
link_to external_snippet_icon('doc-code'), snippet_raw_url, class: 'btn', target: '_blank', rel: 'noopener noreferrer', title: 'Open raw'
end
def embedded_snippet_download_button
......
......@@ -124,7 +124,7 @@ class Notify < BaseMailer
fallback_reply_message_id = "<reply-#{reply_key}@#{Gitlab.config.gitlab.host}>".freeze
headers['References'] ||= []
headers['References'] << fallback_reply_message_id
headers['References'].unshift(fallback_reply_message_id)
@reply_by_email = true
end
......@@ -158,7 +158,7 @@ class Notify < BaseMailer
def mail_answer_thread(model, headers = {})
headers['Message-ID'] = "<#{SecureRandom.hex}@#{Gitlab.config.gitlab.host}>"
headers['In-Reply-To'] = message_id(model)
headers['References'] = message_id(model)
headers['References'] = [message_id(model)]
headers[:subject]&.prepend('Re: ')
......
......@@ -90,34 +90,17 @@ module Routable
end
def full_name
if route && route.name.present?
@full_name ||= route.name # rubocop:disable Gitlab/ModuleWithInstanceVariables
else
update_route if persisted?
build_full_name
end
route&.name || build_full_name
end
# Every time `project.namespace.becomes(Namespace)` is called for polymorphic_path,
# a new instance is instantiated, and we end up duplicating the same query to retrieve
# the route. Caching this per request ensures that even if we have multiple instances,
# we will not have to duplicate work, avoiding N+1 queries in some cases.
def full_path
return uncached_full_path unless RequestStore.active? && persisted?
RequestStore[full_path_key] ||= uncached_full_path
route&.path || build_full_path
end
def full_path_components
full_path.split('/')
end
def expires_full_path_cache
RequestStore.delete(full_path_key) if RequestStore.active?
@full_path = nil # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
def build_full_path
if parent && path
parent.full_path + '/' + path
......@@ -138,16 +121,6 @@ module Routable
self.errors[:path].concat(route_path_errors) if route_path_errors
end
def uncached_full_path
if route && route.path.present?
@full_path ||= route.path # rubocop:disable Gitlab/ModuleWithInstanceVariables
else
update_route if persisted?
build_full_path
end
end
def full_name_changed?
name_changed? || parent_changed?
end
......@@ -156,10 +129,6 @@ module Routable
path_changed? || parent_changed?
end
def full_path_key
@full_path_key ||= "routable/full_path/#{self.class.name}/#{self.id}"
end
def build_full_name
if parent && name
parent.human_name + ' / ' + name
......@@ -168,18 +137,9 @@ module Routable
end
end
def update_route
return if Gitlab::Database.read_only?
prepare_route
route.save
end
def prepare_route
route || build_route(source: self)
route.path = build_full_path
route.name = build_full_name
@full_path = nil # rubocop:disable Gitlab/ModuleWithInstanceVariables
@full_name = nil # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
end
......@@ -11,8 +11,6 @@ module Storage
Namespace.find(parent_id_was) # raise NotFound early if needed
end
expires_full_path_cache
move_repositories
if parent_changed?
......
class DeployToken < ActiveRecord::Base
include Expirable
include TokenAuthenticatable
include PolicyActor
add_authentication_token_field :token
AVAILABLE_SCOPES = %i(read_repository read_registry).freeze
......@@ -58,10 +59,6 @@ class DeployToken < ActiveRecord::Base
write_attribute(:expires_at, value.presence || Forever.date)
end
def admin?
false
end
private
def ensure_at_least_one_scope
......
......@@ -304,7 +304,6 @@ class Namespace < ActiveRecord::Base
def write_projects_repository_config
all_projects.find_each do |project|
project.expires_full_path_cache # we need to clear cache to validate renames correctly
project.write_repository_config
end
end
......
......@@ -1238,8 +1238,6 @@ class Project < ActiveRecord::Base
return true if skip_disk_validation
return false unless repository_storage
expires_full_path_cache # we need to clear cache to validate renames correctly
# Check if repository with same path already exists on disk we can
# skip this for the hashed storage because the path does not change
if legacy_storage? && repository_with_same_path_already_exists?
......@@ -1618,7 +1616,6 @@ class Project < ActiveRecord::Base
# When we import a project overwriting the original project, there
# is a move operation. In that case we don't want to send the instructions.
send_move_instructions(full_path_was) unless import_started?
expires_full_path_cache
self.old_path_with_namespace = full_path_was
SystemHooksService.new.execute_hooks_for(self, :rename)
......
# frozen_string_literal: true
# Include this module if we want to pass something else than the user to
# check policies. This defines several methods which the policy checker
# would call and check.
module PolicyActor
extend ActiveSupport::Concern
def blocked?
false
end
def admin?
false
end
def external?
false
end
def internal?
false
end
def access_locked?
false
end
def required_terms_not_accepted?
false
end
def can_create_group
false
end
end
......@@ -11,10 +11,15 @@ class PipelineSerializer < BaseSerializer
:retryable_builds,
:cancelable_statuses,
:trigger_requests,
:project,
:manual_actions,
:artifacts,
{ pending_builds: :project }
{
pending_builds: :project,
project: [:route, { namespace: :route }],
artifacts: {
project: [:route, { namespace: :route }]
}
}
])
end
......
......@@ -77,7 +77,6 @@ module Projects
Gitlab::PagesTransfer.new.move_project(project.path, @old_namespace.full_path, @new_namespace.full_path)
project.old_path_with_namespace = @old_path
project.expires_full_path_cache
write_repository_config(@new_path)
......
......@@ -17,7 +17,7 @@
- if project.archived
%span.badge.badge-warning archived
.title
= link_to [:admin, project.namespace.becomes(Namespace), project] do
= link_to(admin_namespace_project_path(project.namespace, project)) do
.dash-project-avatar
.avatar-container.s40
= project_icon(project, alt: '', class: 'avatar project-avatar s40')
......
......@@ -67,5 +67,5 @@
%button.navbar-toggler.d-block.d-sm-none{ type: 'button' }
%span.sr-only= _("Toggle navigation")
= sprite_icon('more', size: 12, css_class: 'more-icon js-navbar-toggle-right')
= sprite_icon('ellipsis_h', size: 12, css_class: 'more-icon js-navbar-toggle-right')
= sprite_icon('close', size: 12, css_class: 'close-icon js-navbar-toggle-left')
......@@ -15,7 +15,7 @@
= nav_link(path: ['groups#show', 'groups#activity', 'groups#subgroups', 'analytics#show'], html_options: { class: 'home' }) do
= link_to group_path(@group) do
.nav-icon-container
= sprite_icon('project')
= sprite_icon('home')
%span.nav-item-name
= _('Overview')
......
......@@ -110,7 +110,7 @@
= nav_link(controller: :gpg_keys) do
= link_to profile_gpg_keys_path do
.nav-icon-container
= sprite_icon('key-2')
= sprite_icon('key-modern')
%span.nav-item-name
= _('GPG Keys')
%ul.sidebar-sub-level-items.is-fly-out-only
......
......@@ -11,7 +11,7 @@
= nav_link(path: sidebar_projects_paths, html_options: { class: 'home' }) do
= link_to project_path(@project), class: 'shortcuts-project' do
.nav-icon-container
= sprite_icon('project')
= sprite_icon('home')
%span.nav-item-name
= _('Project')
......@@ -40,7 +40,7 @@
= nav_link(controller: sidebar_repository_paths) do
= link_to project_tree_path(@project), class: 'shortcuts-tree' do
.nav-icon-container
= sprite_icon('doc_text')
= sprite_icon('doc-text')
%span.nav-item-name
= _('Repository')
......
......@@ -86,7 +86,7 @@
- HasStatus::ORDERED_STATUSES.each do |build_status|
- builds.select{|build| build.status == build_status}.each do |build|
.build-job{ class: sidebar_build_class(build, @build), data: { stage: build.stage } }
- tooltip = sanitize(build.tooltip_message)
- tooltip = sanitize(build.tooltip_message.dup)
= link_to(project_job_path(@project, build), data: { toggle: 'tooltip', html: 'true', title: tooltip, container: 'body' }) do
= sprite_icon('arrow-right', size:16, css_class: 'icon-arrow-right')
%span{ class: "ci-status-icon-#{build.status}" }
......
......@@ -2,7 +2,7 @@
.gitlab-embed-snippets
.js-file-title.file-title-flex-parent
.file-header-content
= external_snippet_icon('doc_text')
= external_snippet_icon('doc-text')
%strong.file-title-name
%a.gitlab-embedded-snippets-title{ href: url_for(only_path: false, overwrite_params: nil) }
......
---
title: Rework some projects table indexes around repository_storage field
merge_request: 20377
author:
type: fixed
---
title: Fix navigation to First and Next discussion on MR Changes tab
merge_request: 20434
author:
type: fixed
---
title: Fix rendering of the context lines in MR diffs page
merge_request: 20642
author:
type: fixed
---
title: Fix autosave and ESC confirmation issues for MR discussions
merge_request: 20569
author:
type: fixed
---
title: Fix showing outdated discussions on Changes tab
merge_request: 20445
author:
type: fixed
---
title: Fixed IDE not opening JSON files
merge_request: 20798
author:
type: fixed
---
title: Don't overflow project/group dropdown results
merge_request: 20704
author: gfyoung
type: fixed
---
title: Rails5 update Gemfile.rails5.lock
merge_request: 20858
author: Jasper Maes
type: fixed
---
title: Stop dynamically creating project and namespace routes
merge_request: 20313
author:
type: performance
---
title: Put fallback reply-key address first in the References header
merge_request: 20871
author:
type: changed
---
title: Reduces the client side memory footprint on merge requests
merge_request: 20744
author:
type: performance
---
title: Disable Gitaly timeouts when creating or restoring backups
merge_request: 20810
author:
type: fixed
......@@ -43,6 +43,7 @@ module Gitlab
#{config.root}/app/models/members
#{config.root}/app/models/project_services
#{config.root}/app/workers/concerns
#{config.root}/app/policies/concerns
#{config.root}/app/services/concerns
#{config.root}/app/serializers/concerns
#{config.root}/app/finders/concerns
......
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class RemoveOrphanedRoutes < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
class Route < ActiveRecord::Base
self.table_name = 'routes'
include EachBatch
def self.orphaned_namespace_routes
where(source_type: 'Namespace')
.where('NOT EXISTS ( SELECT 1 FROM namespaces WHERE namespaces.id = routes.source_id )')
end
def self.orphaned_project_routes
where(source_type: 'Project')
.where('NOT EXISTS ( SELECT 1 FROM projects WHERE projects.id = routes.source_id )')
end
end
def up
# Some of these queries can take up to 10 seconds to run on GitLab.com,
# which is pretty close to our 15 second statement timeout. To ensure a
# smooth deployment procedure we disable the statement timeouts for this
# migration, just in case.
disable_statement_timeout
# On GitLab.com there are around 4000 orphaned project routes, and around
# 150 orphaned namespace routes.
[
Route.orphaned_project_routes,
Route.orphaned_namespace_routes
].each do |relation|
relation.each_batch(of: 1_000) do |batch|
batch.delete_all
end
end
end
def down
# There is no way to restore orphaned routes, and this doesn't make any
# sense anyway.
end
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
# This migration generates missing routes for any projects and namespaces that
# don't already have a route.
#
# On GitLab.com this would insert 611 project routes, and 0 namespace routes.
# The exact number could vary per instance, so we take care of both just in
# case.
class GenerateMissingRoutes < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
class User < ActiveRecord::Base
self.table_name = 'users'
end
class Route < ActiveRecord::Base
self.table_name = 'routes'
end
module Routable
def build_full_path
if parent && path
parent.build_full_path + '/' + path
else
path
end
end
def build_full_name
if parent && name
parent.human_name + ' / ' + name
else
name
end
end
def human_name
build_full_name
end
def attributes_for_insert
time = Time.zone.now
{
# We can't use "self.class.name" here as that would include the
# migration namespace.
source_type: source_type_for_route,
source_id: id,
created_at: time,
updated_at: time,
name: build_full_name,
# The route path might already be taken. Instead of trying to generate a
# new unique name on every conflict, we just append the row ID to the
# route path.
path: "#{build_full_path}-#{id}"
}
end
end
class Project < ActiveRecord::Base
self.table_name = 'projects'
include EachBatch
include GenerateMissingRoutes::Routable
belongs_to :namespace, class_name: 'GenerateMissingRoutes::Namespace'
has_one :route,
as: :source,
inverse_of: :source,
class_name: 'GenerateMissingRoutes::Route'
alias_method :parent, :namespace
alias_attribute :parent_id, :namespace_id
def self.without_routes
where(
'NOT EXISTS (
SELECT 1
FROM routes
WHERE source_type = ?
AND source_id = projects.id
)',
'Project'
)
end
def source_type_for_route
'Project'
end
end
class Namespace < ActiveRecord::Base
self.table_name = 'namespaces'
include EachBatch
include GenerateMissingRoutes::Routable
belongs_to :parent, class_name: 'GenerateMissingRoutes::Namespace'
belongs_to :owner, class_name: 'GenerateMissingRoutes::User'
has_one :route,
as: :source,
inverse_of: :source,
class_name: 'GenerateMissingRoutes::Route'