Skip to content
Snippets Groups Projects
Commit dc889678 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent cd52759e
No related branches found
No related tags found
No related merge requests found
Showing
with 149 additions and 96 deletions
Loading
Loading
@@ -25,7 +25,7 @@ class Identity < ApplicationRecord
 
def self.normalize_uid(provider, uid)
if Gitlab::Auth::OAuth::Provider.ldap_provider?(provider)
Gitlab::Auth::LDAP::Person.normalize_dn(uid)
Gitlab::Auth::Ldap::Person.normalize_dn(uid)
else
uid.to_s
end
Loading
Loading
Loading
Loading
@@ -98,6 +98,10 @@ class ProjectImportState < ApplicationRecord
 
Gitlab::SidekiqStatus.set(jid, StuckImportJobsWorker::IMPORT_JOBS_EXPIRATION)
end
def self.jid_by(project_id:, status:)
select(:jid).with_status(status).find_by(project_id: project_id)
end
end
 
ProjectImportState.prepend_if_ee('EE::ProjectImportState')
Loading
Loading
@@ -1562,7 +1562,7 @@ class User < ApplicationRecord
 
def read_only_attribute?(attribute)
if Feature.enabled?(:ldap_readonly_attributes, default_enabled: true)
enabled = Gitlab::Auth::LDAP::Config.enabled?
enabled = Gitlab::Auth::Ldap::Config.enabled?
read_only = attribute.to_sym.in?(UserSyncedAttributesMetadata::SYNCABLE_ATTRIBUTES)
 
return true if enabled && read_only
Loading
Loading
Loading
Loading
@@ -16,7 +16,7 @@
Password authentication enabled for Git over HTTP(S)
.form-text.text-muted
When disabled, a Personal Access Token
- if Gitlab::Auth::LDAP::Config.enabled?
- if Gitlab::Auth::Ldap::Config.enabled?
or LDAP password
must be used to authenticate.
- if omniauth_enabled? && button_based_providers.any?
Loading
Loading
- if can_admin_cluster?(current_user, @cluster)
.settings.expanded.border-0.m-0
%p
= s_('ClusterIntegration|Advanced options on this Kubernetes cluster’s integration')
.settings-content#advanced-settings-section
= render 'clusters/clusters/advanced_settings'
- active = params[:tab] == 'settings'
- if can_admin_cluster?(current_user, @cluster)
%li.nav-item{ role: 'presentation' }
%a#cluster-settings-tab.nav-link{ class: active_when(active), href: clusterable.cluster_path(@cluster.id, params: {tab: 'settings'}) }
%span= _('Advanced Settings')
.cluster-applications-table#js-cluster-applications
- active = params[:tab] == 'apps'
%li.nav-item{ role: 'presentation' }
%a#cluster-apps-tab.nav-link.qa-applications{ class: active_when(active), href: clusterable.cluster_path(@cluster.id, params: {tab: 'apps'}) }
%span= _('Applications')
%section#cluster-integration
- unless @cluster.status_name.in? %i/scheduled creating/
= render 'form'
- unless @cluster.status_name.in? %i/scheduled creating/
= render_if_exists 'projects/clusters/prometheus_graphs'
.cluster-applications-table#js-cluster-applications
%section.settings#js-cluster-details{ class: ('expanded' if expanded) }
.settings-header
%h4= s_('ClusterIntegration|Kubernetes cluster details')
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p= s_('ClusterIntegration|See and edit the details for your Kubernetes cluster')
.settings-content
= render 'clusters/platforms/kubernetes/form', cluster: @cluster, platform: @cluster.platform_kubernetes, update_cluster_url_path: clusterable.cluster_path(@cluster)
%section.settings.no-animate#js-cluster-advanced-settings{ class: ('expanded' if expanded) }
.settings-header
%h4= _('Advanced settings')
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p= s_("ClusterIntegration|Advanced options on this Kubernetes cluster's integration")
.settings-content#advanced-settings-section
= render 'advanced_settings'
%section#cluster-integration
= render 'gitlab_integration_form'
%section.settings.no-animate{ class: ('expanded' if expanded) }
.settings-header
%h4= s_('ClusterIntegration|Provider details')
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p= s_('ClusterIntegration|See and edit the details for your Kubernetes cluster')
.settings-content
= render 'provider_details_form', cluster: @cluster, platform: @cluster.platform_kubernetes, update_cluster_url_path: clusterable.cluster_path(@cluster)
- active = params[:tab] == 'details' || !params[:tab].present?
%li.nav-item{ role: 'presentation' }
%a#cluster-details-tab.nav-link.qa-details{ class: active_when(active), href: clusterable.cluster_path(@cluster.id, params: {tab: 'details'}) }
%span= _('Details')
= form_for @cluster, url: clusterable.cluster_path(@cluster), as: :cluster, html: { class: 'cluster_integration_form' } do |field|
= form_for @cluster, url: clusterable.cluster_path(@cluster), as: :cluster, html: { class: 'js-cluster-integration-form' } do |field|
= form_errors(@cluster)
.form-group
%h5= s_('ClusterIntegration|Integration status')
%label.append-bottom-0.js-cluster-enable-toggle-area
= render "shared/buttons/project_feature_toggle", is_checked: @cluster.enabled?, label: s_("ClusterIntegration|Toggle Kubernetes cluster"), disabled: !can?(current_user, :update_cluster, @cluster), data: { qa_selector: 'integration_status_toggle' } do
= field.hidden_field :enabled, { class: 'js-project-feature-toggle-input'}
.form-text.text-muted= s_('ClusterIntegration|Enable or disable GitLab\'s connection to your Kubernetes cluster.')
.d-flex.align-items-center
%h4.pr-2.m-0
= s_('ClusterIntegration|GitLab Integration')
%label.append-bottom-0.js-cluster-enable-toggle-area{ title: s_('ClusterIntegration|Enable or disable GitLab\'s connection to your Kubernetes cluster.'), data: { toggle: 'tooltip', container: 'body' } }
= render "shared/buttons/project_feature_toggle", is_checked: @cluster.enabled?, label: s_("ClusterIntegration|Toggle Kubernetes cluster"), disabled: !can?(current_user, :update_cluster, @cluster), data: { qa_selector: 'integration_status_toggle' } do
= field.hidden_field :enabled, { class: 'js-project-feature-toggle-input'}
 
.form-group
%h5= s_('ClusterIntegration|Environment scope')
Loading
Loading
@@ -17,7 +18,8 @@
- environment_scope_url = help_page_path('user/project/clusters/index', anchor: 'base-domain')
- environment_scope_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: environment_scope_url }
.form-text.text-muted
%code *
%code
= _('*')
= s_("ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}").html_safe % { environment_scope_start: environment_scope_start, environment_scope_end: '</a>'.html_safe }
 
.form-group
Loading
Loading
@@ -29,7 +31,8 @@
= s_('ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain.').html_safe % { auto_devops_start: auto_devops_start, auto_devops_end: '</a>'.html_safe }
%span{ :class => ["js-ingress-domain-help-text", ("hide" unless @cluster.application_ingress_external_ip.present?)] }
= s_('ClusterIntegration|Alternatively')
%code{ :class => "js-ingress-domain-snippet" } #{@cluster.application_ingress_external_ip}.nip.io
%code{ :class => "js-ingress-domain-snippet" }
= s_('ClusterIntegration|%{external_ip}.nip.io').html_safe % { external_ip: @cluster.application_ingress_external_ip }
= s_('ClusterIntegration| can be used instead of a custom domain.')
- custom_domain_url = help_page_path('user/clusters/applications.md', anchor: 'pointing-your-dns-at-the-external-endpoint')
- custom_domain_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: custom_domain_url }
Loading
Loading
= bootstrap_form_for cluster, url: update_cluster_url_path, html: { class: 'gl-show-field-errors' },
= bootstrap_form_for cluster, url: update_cluster_url_path, html: { class: 'js-provider-details gl-show-field-errors' },
as: :cluster do |field|
- copy_name_btn = clipboard_button(text: cluster.name, title: s_('ClusterIntegration|Copy Kubernetes cluster name'),
class: 'input-group-text btn-default') if cluster.read_only_kubernetes_platform_fields?
Loading
Loading
Loading
Loading
@@ -5,8 +5,6 @@
- manage_prometheus_path = edit_project_service_path(@cluster.project, 'prometheus') if @project
- cluster_environments_path = clusterable.environments_cluster_path(@cluster)
 
- expanded = expanded_by_default?
- status_path = clusterable.cluster_status_cluster_path(@cluster.id, format: :json) if can?(current_user, :admin_cluster, @cluster)
.edit-cluster-form.js-edit-cluster-form{ data: { status_path: status_path,
install_helm_path: clusterable.install_applications_cluster_path(@cluster, :helm),
Loading
Loading
@@ -44,7 +42,19 @@
%h4= @cluster.name
= render 'banner'
 
- if cluster_environments_path.present?
= render_if_exists 'clusters/clusters/cluster_environments', expanded: expanded
- else
= render 'configure', expanded: expanded
- if cluster_created?(@cluster)
.js-toggle-container
%ul.nav-links.mobile-separator.nav.nav-tabs{ role: 'tablist' }
= render 'details_tab'
= render_if_exists 'clusters/clusters/environments_tab'
= render_if_exists 'clusters/clusters/health_tab'
= render 'applications_tab'
= render 'advanced_settings_tab'
.tab-content.py-3
.tab-pane.active{ role: 'tabpanel' }
= render_cluster_info_tab_content(params[:tab], expanded_by_default?)
Loading
Loading
@@ -8,15 +8,12 @@ module Gitlab
# stage.
class AdvanceStageWorker # rubocop:disable Scalability/IdempotentWorker
include ApplicationWorker
include ::Gitlab::Import::AdvanceStage
 
sidekiq_options dead: false
feature_category :importers
 
INTERVAL = 30.seconds.to_i
# The number of seconds to wait (while blocking the thread) before
# continuing to the next waiter.
BLOCKING_WAIT_TIME = 5
private
 
# The known importer stages and their corresponding Sidekiq workers.
STAGES = {
Loading
Loading
@@ -26,49 +23,9 @@ module Gitlab
finish: Stage::FinishImportWorker
}.freeze
 
# project_id - The ID of the project being imported.
# waiters - A Hash mapping Gitlab::JobWaiter keys to the number of
# remaining jobs.
# next_stage - The name of the next stage to start when all jobs have been
# completed.
def perform(project_id, waiters, next_stage)
return unless import_state = find_import_state(project_id)
new_waiters = wait_for_jobs(waiters)
if new_waiters.empty?
# We refresh the import JID here so workers importing individual
# resources (e.g. notes) don't have to do this all the time, reducing
# the pressure on Redis. We _only_ do this once all jobs are done so
# we don't get stuck forever if one or more jobs failed to notify the
# JobWaiter.
import_state.refresh_jid_expiration
STAGES.fetch(next_stage.to_sym).perform_async(project_id)
else
self.class.perform_in(INTERVAL, project_id, new_waiters, next_stage)
end
end
def wait_for_jobs(waiters)
waiters.each_with_object({}) do |(key, remaining), new_waiters|
waiter = JobWaiter.new(remaining, key)
# We wait for a brief moment of time so we don't reschedule if we can
# complete the work fast enough.
waiter.wait(BLOCKING_WAIT_TIME)
next unless waiter.jobs_remaining.positive?
new_waiters[waiter.key] = waiter.jobs_remaining
end
end
# rubocop: disable CodeReuse/ActiveRecord
def find_import_state(project_id)
ProjectImportState.select(:jid).with_status(:started).find_by(project_id: project_id)
def next_stage_worker(next_stage)
STAGES.fetch(next_stage.to_sym)
end
# rubocop: enable CodeReuse/ActiveRecord
end
end
end
# frozen_string_literal: true
module Gitlab
module Import
module AdvanceStage
INTERVAL = 30.seconds.to_i
# The number of seconds to wait (while blocking the thread) before
# continuing to the next waiter.
BLOCKING_WAIT_TIME = 5
# project_id - The ID of the project being imported.
# waiters - A Hash mapping Gitlab::JobWaiter keys to the number of
# remaining jobs.
# next_stage - The name of the next stage to start when all jobs have been
# completed.
def perform(project_id, waiters, next_stage)
return unless import_state = find_import_state(project_id)
new_waiters = wait_for_jobs(waiters)
if new_waiters.empty?
# We refresh the import JID here so workers importing individual
# resources (e.g. notes) don't have to do this all the time, reducing
# the pressure on Redis. We _only_ do this once all jobs are done so
# we don't get stuck forever if one or more jobs failed to notify the
# JobWaiter.
import_state.refresh_jid_expiration
next_stage_worker(next_stage).perform_async(project_id)
else
self.class.perform_in(INTERVAL, project_id, new_waiters, next_stage)
end
end
def wait_for_jobs(waiters)
waiters.each_with_object({}) do |(key, remaining), new_waiters|
waiter = JobWaiter.new(remaining, key)
# We wait for a brief moment of time so we don't reschedule if we can
# complete the work fast enough.
waiter.wait(BLOCKING_WAIT_TIME)
next unless waiter.jobs_remaining.positive?
new_waiters[waiter.key] = waiter.jobs_remaining
end
end
def find_import_state(project_id)
ProjectImportState.jid_by(project_id: project_id, status: :started)
end
private
def next_stage_worker(next_stage)
raise NotImplementedError
end
end
end
end
Loading
Loading
@@ -77,11 +77,6 @@ class PostReceive # rubocop:disable Scalability/IdempotentWorker
 
return false unless user
 
# We can remove once we implement multi-file snippets
# https://gitlab.com/gitlab-org/gitlab/-/issues/39269
blob = snippet.blobs.first
snippet.update(file_name: blob.path, content: blob.data) if blob
# At the moment, we only expires the repository caches.
# In the future we might need to call ProjectCacheWorker
# (or the custom class we create) to update the snippet
Loading
Loading
---
title: Fix White syntax highlighting theme in Monaco to closely match the Pygments theme.
merge_request: 25966
author:
type: fixed
---
title: Fix evidence SHA clipboard hover text.
merge_request: 26608
author: Gilang Gumilar
type: fixed
---
title: Expose assets filepath URL on UI
merge_request: 25635
author:
type: added
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment