This instance will be upgraded to Heptapod 0.26.0rc1 on 2021-10-26 at 14:30 UTC+2 (a few minutes of down time)

Commit 72c08aa1 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent aa8d137f744e
Please view this file on the master branch, on stable branches it's out of date.
## 12.7.1
### Fixed (1 change)
- Fix create/delete API calls for approval rules. !23107
## 12.7.0
### Removed (2 changes)
......
......@@ -4,7 +4,19 @@ entry.
 
## 12.7.1
 
- No changes.
### Fixed (6 changes)
- Fix loading of sub-epics caused by wrong subscription check. !23184
- Fix Bitbucket Server importer error handler. !23310
- Fixes random passwords generated not conforming to minimum_password_length setting. !23387
- Reverts MR diff redesign which fixes Web IDE visual bugs including file dropdown not showing up. !23428
- Allow users to sign out on a read-only instance. !23545
- Remove invalid data from jira_tracker_data table. !23621
### Added (1 change)
- Close Issue when resolving corresponding Sentry error. !22744
 
## 12.7.0
 
......
......@@ -34,7 +34,10 @@ export default {
projectPath: this.projectPath,
};
},
update: data => data.project.userPermissions,
update: data => data.project?.userPermissions,
error(error) {
throw error;
},
},
},
mixins: [getRefMixin],
......@@ -172,7 +175,7 @@ export default {
);
}
if (this.userPermissions.pushCode) {
if (this.userPermissions?.pushCode) {
items.push(
{
type: ROW_TYPES.divider,
......
......@@ -40,16 +40,19 @@ export default {
};
},
update: data => {
const pipelines = data.project.repository.tree.lastCommit.pipelines.edges;
const pipelines = data.project?.repository?.tree?.lastCommit?.pipelines?.edges;
return {
...data.project.repository.tree.lastCommit,
pipeline: pipelines.length && pipelines[0].node,
...data.project?.repository?.tree?.lastCommit,
pipeline: pipelines?.length && pipelines[0].node,
};
},
context: {
isSingleRequest: true,
},
error(error) {
throw error;
},
},
},
props: {
......@@ -62,7 +65,7 @@ export default {
data() {
return {
projectPath: '',
commit: {},
commit: null,
showDescription: false,
};
},
......@@ -79,6 +82,11 @@ export default {
return this.commit.sha.substr(0, 8);
},
},
watch: {
currentPath() {
this.commit = null;
},
},
methods: {
toggleShowDescription() {
this.showDescription = !this.showDescription;
......@@ -91,7 +99,7 @@ export default {
<template>
<div class="info-well d-none d-sm-flex project-last-commit commit p-3">
<gl-loading-icon v-if="isLoading" size="md" color="dark" class="m-auto" />
<template v-else>
<template v-else-if="commit">
<user-avatar-link
v-if="commit.author"
:link-href="commit.author.webUrl"
......
......@@ -86,7 +86,8 @@ export default {
},
})
.then(({ data }) => {
if (!data) return;
if (data.errors) throw data.errors;
if (!data?.project?.repository) return;
const pageInfo = this.hasNextPage(data.project.repository.tree);
......@@ -99,12 +100,15 @@ export default {
{},
);
if (pageInfo && pageInfo.hasNextPage) {
if (pageInfo?.hasNextPage) {
this.nextPageCursor = pageInfo.endCursor;
this.fetchFiles();
}
})
.catch(() => createFlash(__('An error occurred while fetching folder content.')));
.catch(error => {
createFlash(__('An error occurred while fetching folder content.'));
throw error;
});
},
normalizeData(key, data) {
return this.entries[key].concat(data.map(({ node }) => node));
......
......@@ -23,7 +23,7 @@ export default function setupVueRepositoryList() {
projectPath,
projectShortPath,
ref,
vueFileListLfsBadge: gon?.features?.vueFileListLfsBadge,
vueFileListLfsBadge: gon.features?.vueFileListLfsBadge || false,
commits: [],
},
});
......
......@@ -66,7 +66,7 @@ def runner_params
# rubocop: disable CodeReuse/ActiveRecord
def assign_builds_and_projects
@builds = runner.builds.order('id DESC').first(30)
@builds = runner.builds.order('id DESC').preload_project_and_pipeline_project.first(30)
@projects =
if params[:search].present?
::Project.search(params[:search])
......@@ -75,7 +75,8 @@ def assign_builds_and_projects
end
@projects = @projects.where.not(id: runner.projects.select(:id)) if runner.projects.any?
@projects = @projects.page(params[:page]).per(30)
@projects = @projects.inc_routes
@projects = @projects.page(params[:page]).per(30).without_count
end
# rubocop: enable CodeReuse/ActiveRecord
end
......@@ -7,14 +7,14 @@ class Import::BaseController < ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def find_already_added_projects(import_type)
current_user.created_projects.where(import_type: import_type).includes(:import_state)
current_user.created_projects.where(import_type: import_type).with_import_state
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def find_jobs(import_type)
current_user.created_projects
.includes(:import_state)
.with_import_state
.where(import_type: import_type)
.to_json(only: [:id], methods: [:import_status])
end
......
......@@ -82,7 +82,7 @@ def jobs
# rubocop: disable CodeReuse/ActiveRecord
def filter_added_projects(import_type, import_sources)
current_user.created_projects.where(import_type: import_type, import_source: import_sources).includes(:import_state)
current_user.created_projects.where(import_type: import_type, import_source: import_sources).with_import_state
end
# rubocop: enable CodeReuse/ActiveRecord
......
......@@ -87,7 +87,7 @@ def find_already_added_projects
group.all_projects
.where(import_type: 'manifest')
.where(creator_id: current_user)
.includes(:import_state)
.with_import_state
end
# rubocop: enable CodeReuse/ActiveRecord
......
......@@ -12,16 +12,14 @@ def initialize(user)
# visible by this user.
#
# Returns an ActiveRecord::Relation.
# rubocop: disable CodeReuse/ActiveRecord
def execute(current_user = nil)
# Do not show contributed projects if the user profile is private.
return Project.none unless can_read_profile?(current_user)
segments = all_projects(current_user)
find_union(segments, Project).includes(:namespace).order_id_desc
find_union(segments, Project).with_namespace.order_id_desc
end
# rubocop: enable CodeReuse/ActiveRecord
private
......
......@@ -17,15 +17,13 @@ def initialize(user, params = {})
# min_access_level: integer
#
# Returns an ActiveRecord::Relation.
# rubocop: disable CodeReuse/ActiveRecord
def execute(current_user = nil)
return Project.none unless can?(current_user, :read_user_profile, @user)
segments = all_projects(current_user)
find_union(segments, Project).includes(:namespace).order_updated_desc
find_union(segments, Project).with_namespace.order_updated_desc
end
# rubocop: enable CodeReuse/ActiveRecord
private
......
# frozen_string_literal: true
module AnalyticsNavbarHelper
class NavbarSubItem
attr_reader :title, :path, :link, :link_to_options
def initialize(title:, path:, link:, link_to_options: {})
@title = title
@path = path
@link = link
@link_to_options = link_to_options.merge(title: title)
end
end
def project_analytics_navbar_links(project, current_user)
[
cycle_analytics_navbar_link(project, current_user),
repository_analytics_navbar_link(project, current_user),
ci_cd_analytics_navbar_link(project, current_user)
].compact
end
private
def navbar_sub_item(args)
NavbarSubItem.new(args)
end
def cycle_analytics_navbar_link(project, current_user)
return unless Feature.enabled?(:analytics_pages_under_project_analytics_sidebar, project)
return unless project_nav_tab?(:cycle_analytics)
navbar_sub_item(
title: _('Cycle Analytics'),
path: 'cycle_analytics#show',
link: project_cycle_analytics_path(project),
link_to_options: { class: 'shortcuts-project-cycle-analytics' }
)
end
def repository_analytics_navbar_link(project, current_user)
return if Feature.disabled?(:analytics_pages_under_project_analytics_sidebar, project)
return if project.empty_repo?
navbar_sub_item(
title: _('Repository Analytics'),
path: 'graphs#charts',
link: charts_project_graph_path(project, current_ref),
link_to_options: { class: 'shortcuts-repository-charts' }
)
end
def ci_cd_analytics_navbar_link(project, current_user)
return unless Feature.enabled?(:analytics_pages_under_project_analytics_sidebar, project)
return unless project_nav_tab?(:pipelines)
return unless project.feature_available?(:builds, current_user) || !project.empty_repo?
navbar_sub_item(
title: _('CI / CD Analytics'),
path: 'pipelines#charts',
link: charts_project_pipelines_path(project)
)
end
end
AnalyticsNavbarHelper.prepend_if_ee('EE::AnalyticsNavbarHelper')
......@@ -403,6 +403,10 @@ def get_project_nav_tabs(project, current_user)
nav_tabs << :operations
end
if can?(current_user, :read_cycle_analytics, project)
nav_tabs << :cycle_analytics
end
tab_ability_map.each do |tab, ability|
if can?(current_user, ability, project)
nav_tabs << tab
......@@ -643,7 +647,6 @@ def sidebar_projects_paths
projects#show
projects#activity
releases#index
cycle_analytics#show
]
end
......
......@@ -12,6 +12,7 @@ module TabHelper
# :action - One or more action names to check (optional).
# :path - A shorthand path, such as 'dashboard#index', to check (optional).
# :html_options - Extra options to be passed to the list element (optional).
# :unless - Callable object to skip rendering the 'active' class on `li` element (optional).
# block - An optional block that will become the contents of the returned
# `li` element.
#
......@@ -56,6 +57,14 @@ module TabHelper
# nav_link(path: 'admin/appearances#show') { "Hello"}
# # => '<li class="active">Hello</li>'
#
# # Shorthand path + unless
# # Add `active` class when TreeController is requested, except the `index` action.
# nav_link(controller: 'tree', unless: -> { action_name?('index') }) { "Hello" }
# # => '<li class="active">Hello</li>'
#
# # When `TreeController#index` is requested
# # => '<li>Hello</li>'
#
# Returns a list item element String
def nav_link(options = {}, &block)
klass = active_nav_link?(options) ? 'active' : ''
......@@ -73,6 +82,8 @@ def nav_link(options = {}, &block)
end
def active_nav_link?(options)
return false if options[:unless]&.call
if path = options.delete(:path)
unless path.respond_to?(:each)
path = [path]
......
......@@ -172,6 +172,9 @@ def persisted_environment
scope :queued_before, ->(time) { where(arel_table[:queued_at].lt(time)) }
scope :order_id_desc, -> { order('ci_builds.id DESC') }
PROJECT_ROUTE_AND_NAMESPACE_ROUTE = { project: [:project_feature, :route, { namespace: :route }] }.freeze
scope :preload_project_and_pipeline_project, -> { preload(PROJECT_ROUTE_AND_NAMESPACE_ROUTE, pipeline: PROJECT_ROUTE_AND_NAMESPACE_ROUTE) }
acts_as_taggable
add_authentication_token_field :token, encrypted: :optional
......
......@@ -411,6 +411,8 @@ class Project < ApplicationRecord
scope :with_project_feature, -> { joins('LEFT JOIN project_features ON projects.id = project_features.project_id') }
scope :inc_routes, -> { includes(:route, namespace: :route) }
scope :with_statistics, -> { includes(:statistics) }
scope :with_namespace, -> { includes(:namespace) }
scope :with_import_state, -> { includes(:import_state) }
scope :with_service, ->(service) { joins(service).eager_load(service) }
scope :with_shared_runners, -> { where(shared_runners_enabled: true) }
scope :with_container_registry, -> { where(container_registry_enabled: true) }
......
......@@ -100,9 +100,7 @@ def change_time_spent(noteable, project, author)
end
def close_after_error_tracking_resolve(issue, project, author)
body = _('resolved the corresponding error and closed the issue.')
create_note(NoteSummary.new(issue, project, author, body, action: 'closed'))
::SystemNotes::IssuablesService.new(noteable: issue, project: project, author: author).close_after_error_tracking_resolve
end
def change_status(noteable, project, author, status, source = nil)
......@@ -243,23 +241,6 @@ def zoom_link_added(issue, project, author)
def zoom_link_removed(issue, project, author)
::SystemNotes::ZoomService.new(noteable: issue, project: project, author: author).zoom_link_removed
end
private
def create_note(note_summary)
note = Note.create(note_summary.note.merge(system: true))
note.system_note_metadata = SystemNoteMetadata.new(note_summary.metadata) if note_summary.metadata?
note
end
def url_helpers
@url_helpers ||= Gitlab::Routing.url_helpers
end
def content_tag(*args)
ActionController::Base.helpers.content_tag(*args)
end
end
SystemNoteService.prepend_if_ee('EE::SystemNoteService')
......@@ -282,6 +282,12 @@ def discussion_lock
create_note(NoteSummary.new(noteable, project, author, body, action: action))
end
def close_after_error_tracking_resolve
body = _('resolved the corresponding error and closed the issue.')
create_note(NoteSummary.new(noteable, project, author, body, action: 'closed'))
end
private
def cross_reference_note_content(gfm_reference)
......
......@@ -48,7 +48,7 @@
= project.full_name
%td
.float-right
= link_to 'Disable', [:admin, project.namespace.becomes(Namespace), project, runner_project], method: :delete, class: 'btn btn-danger btn-sm'
= link_to 'Disable', admin_namespace_project_runner_project_path(project.namespace, project, runner_project), method: :delete, class: 'btn btn-danger btn-sm'
%table.table.unassigned-projects
%thead
......@@ -70,10 +70,10 @@
= project.full_name
%td
.float-right
= form_for [:admin, project.namespace.becomes(Namespace), project, project.runner_projects.new] do |f|
= form_for project.runner_projects.new, url: admin_namespace_project_runner_projects_path(project.namespace, project), method: :post do |f|
= f.hidden_field :runner_id, value: @runner.id
= f.submit 'Enable', class: 'btn btn-sm'
= paginate @projects, theme: "gitlab"
= paginate_without_count @projects
.col-md-6
%h4 Recent jobs served by this Runner
......
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