Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
b8fbfa9c70
commit
d111e00680
|
|
@ -40,4 +40,3 @@ Graphql/ResourceNotAvailableError:
|
|||
- 'ee/app/graphql/mutations/projects/set_locked.rb'
|
||||
- 'ee/app/graphql/resolvers/incident_management/oncall_shifts_resolver.rb'
|
||||
- 'ee/app/graphql/resolvers/product_analytics/visualization_resolver.rb'
|
||||
- 'ee/app/graphql/resolvers/remote_development/workspaces_resolver.rb'
|
||||
|
|
|
|||
|
|
@ -149,7 +149,6 @@ RSpec/BeforeAllRoleAssignment:
|
|||
- 'ee/spec/features/projects/wiki/user_views_wiki_empty_spec.rb'
|
||||
- 'ee/spec/features/projects_spec.rb'
|
||||
- 'ee/spec/features/protected_branches_spec.rb'
|
||||
- 'ee/spec/features/remote_development/workspaces_spec.rb'
|
||||
- 'ee/spec/features/search/user_searches_for_epics_spec.rb'
|
||||
- 'ee/spec/features/search/zoekt/search_spec.rb'
|
||||
- 'ee/spec/features/subscriptions/expiring_subscription_message_spec.rb'
|
||||
|
|
@ -360,7 +359,6 @@ RSpec/BeforeAllRoleAssignment:
|
|||
- 'ee/spec/policies/merge_requests/external_status_check_policy_spec.rb'
|
||||
- 'ee/spec/policies/packages/policies/project_policy_spec.rb'
|
||||
- 'ee/spec/policies/project_policy_spec.rb'
|
||||
- 'ee/spec/policies/remote_development/workspace_policy_spec.rb'
|
||||
- 'ee/spec/policies/requirements_management/requirement_policy_spec.rb'
|
||||
- 'ee/spec/policies/resource_iteration_event_policy_spec.rb'
|
||||
- 'ee/spec/policies/resource_weight_event_policy_spec.rb'
|
||||
|
|
@ -465,8 +463,6 @@ RSpec/BeforeAllRoleAssignment:
|
|||
- 'ee/spec/requests/api/graphql/mutations/projects/set_compliance_framework_spec.rb'
|
||||
- 'ee/spec/requests/api/graphql/mutations/releases/create_spec.rb'
|
||||
- 'ee/spec/requests/api/graphql/mutations/releases/update_spec.rb'
|
||||
- 'ee/spec/requests/api/graphql/mutations/remote_development/workspaces/create_spec.rb'
|
||||
- 'ee/spec/requests/api/graphql/mutations/remote_development/workspaces/update_spec.rb'
|
||||
- 'ee/spec/requests/api/graphql/mutations/requirements_management/create_requirement_spec.rb'
|
||||
- 'ee/spec/requests/api/graphql/mutations/requirements_management/export_requirements_spec.rb'
|
||||
- 'ee/spec/requests/api/graphql/mutations/requirements_management/update_requirement_spec.rb'
|
||||
|
|
|
|||
|
|
@ -127,10 +127,15 @@ export default {
|
|||
},
|
||||
actionsFieldTdClass(value, key, member) {
|
||||
if (this.hasActionButtons(member)) {
|
||||
return 'col-actions';
|
||||
return ['col-actions', 'gl-vertical-align-middle!'];
|
||||
}
|
||||
|
||||
return ['col-actions', 'gl-display-none!', 'gl-lg-display-table-cell!'];
|
||||
return [
|
||||
'col-actions',
|
||||
'gl-display-none!',
|
||||
'gl-lg-display-table-cell!',
|
||||
'gl-vertical-align-middle!',
|
||||
];
|
||||
},
|
||||
tbodyTrAttr(member) {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -32,12 +32,13 @@ export const FIELDS = [
|
|||
asc: 'name_asc',
|
||||
desc: 'name_desc',
|
||||
},
|
||||
tdClass: 'gl-vertical-align-middle!',
|
||||
},
|
||||
{
|
||||
key: FIELD_KEY_SOURCE,
|
||||
label: __('Source'),
|
||||
thClass: 'col-meta',
|
||||
tdClass: 'col-meta',
|
||||
tdClass: 'col-meta gl-vertical-align-middle!',
|
||||
},
|
||||
{
|
||||
key: FIELD_KEY_GRANTED,
|
||||
|
|
@ -46,24 +47,25 @@ export const FIELDS = [
|
|||
asc: 'last_joined',
|
||||
desc: 'oldest_joined',
|
||||
},
|
||||
tdClass: 'gl-vertical-align-middle!',
|
||||
},
|
||||
{
|
||||
key: FIELD_KEY_INVITED,
|
||||
label: __('Invited'),
|
||||
thClass: 'col-meta',
|
||||
tdClass: 'col-meta',
|
||||
tdClass: 'col-meta gl-vertical-align-middle!',
|
||||
},
|
||||
{
|
||||
key: FIELD_KEY_REQUESTED,
|
||||
label: __('Requested'),
|
||||
thClass: 'col-meta',
|
||||
tdClass: 'col-meta',
|
||||
tdClass: 'col-meta gl-vertical-align-middle!',
|
||||
},
|
||||
{
|
||||
key: FIELD_KEY_MAX_ROLE,
|
||||
label: __('Max role'),
|
||||
thClass: 'col-max-role',
|
||||
tdClass: 'col-max-role',
|
||||
tdClass: 'col-max-role gl-vertical-align-middle!',
|
||||
sort: {
|
||||
asc: 'access_level_asc',
|
||||
desc: 'access_level_desc',
|
||||
|
|
@ -73,13 +75,13 @@ export const FIELDS = [
|
|||
key: FIELD_KEY_EXPIRATION,
|
||||
label: __('Expiration'),
|
||||
thClass: 'col-expiration',
|
||||
tdClass: 'col-expiration',
|
||||
tdClass: 'col-expiration gl-vertical-align-middle!',
|
||||
},
|
||||
{
|
||||
key: FIELD_KEY_ACTIVITY,
|
||||
label: s__('Members|Activity'),
|
||||
thClass: 'col-activity',
|
||||
tdClass: 'col-activity',
|
||||
tdClass: 'col-activity gl-vertical-align-middle!',
|
||||
},
|
||||
{
|
||||
key: FIELD_KEY_USER_CREATED_AT,
|
||||
|
|
|
|||
|
|
@ -105,7 +105,6 @@ export default {
|
|||
icon="dash"
|
||||
:aria-label="$options.i18n.removeItem"
|
||||
:title="$options.i18n.removeItem"
|
||||
class="gl-align-self-center gl-mr-2"
|
||||
data-testid="item-remove"
|
||||
@click.stop.prevent="handleItemRemove(item)"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -19,13 +19,7 @@ export default {
|
|||
|
||||
<template>
|
||||
<ul class="gl-p-0 gl-list-style-none">
|
||||
<nav-item
|
||||
v-for="item in items"
|
||||
:key="item.id"
|
||||
:item="item"
|
||||
:link-classes="{ 'gl-py-2!': true }"
|
||||
is-subitem
|
||||
>
|
||||
<nav-item v-for="item in items" :key="item.id" :item="item" is-subitem>
|
||||
<template #icon>
|
||||
<project-avatar
|
||||
:project-id="item.id"
|
||||
|
|
@ -33,7 +27,6 @@ export default {
|
|||
:project-avatar-url="item.avatar"
|
||||
:size="24"
|
||||
aria-hidden="true"
|
||||
class="gl-mr-n2"
|
||||
/>
|
||||
</template>
|
||||
<template #actions>
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ export default {
|
|||
<component :is="tag">
|
||||
<hr v-if="separated" aria-hidden="true" class="gl-mx-4 gl-my-2" />
|
||||
<button
|
||||
class="gl-rounded-base gl-relative gl-display-flex gl-align-items-center gl-line-height-normal gl-mb-2 gl-py-3 gl-px-0 gl-text-black-normal! gl-hover-bg-t-gray-a-08 gl-focus-bg-t-gray-a-08 gl-text-decoration-none! gl-appearance-none gl-border-0 gl-bg-transparent gl-text-left gl-w-full gl-focus--focus"
|
||||
class="gl-rounded-base gl-relative gl-display-flex gl-align-items-center gl-min-h-7 gl-gap-3 gl-mb-2 gl-py-2 gl-px-3 gl-text-black-normal! gl-hover-bg-t-gray-a-08 gl-focus-bg-t-gray-a-08 gl-text-decoration-none! gl-appearance-none gl-border-0 gl-bg-transparent gl-text-left gl-w-full gl-focus--focus"
|
||||
:class="computedLinkClasses"
|
||||
data-qa-selector="menu_section_button"
|
||||
:data-qa-section-name="item.title"
|
||||
|
|
@ -84,17 +84,17 @@ export default {
|
|||
aria-hidden="true"
|
||||
style="width: 3px; border-radius: 3px; margin-right: 1px"
|
||||
></span>
|
||||
<span class="gl-flex-shrink-0 gl-w-6 gl-mx-3">
|
||||
<span class="gl-flex-shrink-0 gl-w-6 gl-display-flex">
|
||||
<slot name="icon">
|
||||
<gl-icon v-if="item.icon" :name="item.icon" class="gl-ml-2 item-icon" />
|
||||
<gl-icon v-if="item.icon" :name="item.icon" class="gl-m-auto item-icon" />
|
||||
</slot>
|
||||
</span>
|
||||
|
||||
<span class="gl-pr-3 gl-text-gray-900 gl-truncate-end">
|
||||
<span class="gl-flex-grow-1 gl-text-gray-900 gl-truncate-end">
|
||||
{{ item.title }}
|
||||
</span>
|
||||
|
||||
<span class="gl-flex-grow-1 gl-text-right gl-mr-3 gl-text-gray-400">
|
||||
<span class="gl-text-right gl-text-gray-400">
|
||||
<gl-icon :name="collapseIcon" />
|
||||
</span>
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -102,9 +102,8 @@ export default {
|
|||
},
|
||||
computedLinkClasses() {
|
||||
return {
|
||||
'gl-py-2': this.isPinnable,
|
||||
'gl-py-3': !this.isPinnable,
|
||||
'gl-mx-2': this.isSubitem,
|
||||
'gl-px-2 gl-mx-2 gl-line-height-normal': this.isSubitem,
|
||||
'gl-px-3': !this.isSubitem,
|
||||
[this.item.link_classes]: this.item.link_classes,
|
||||
...this.linkClasses,
|
||||
};
|
||||
|
|
@ -112,9 +111,6 @@ export default {
|
|||
navItemLinkComponent() {
|
||||
return this.item.to ? NavItemRouterLink : NavItemLink;
|
||||
},
|
||||
iconClasses() {
|
||||
return this.isSubitem === true ? 'gl-ml-2 gl-mr-4' : 'gl-w-6 gl-mx-3';
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -125,7 +121,7 @@ export default {
|
|||
:is="navItemLinkComponent"
|
||||
#default="{ isActive }"
|
||||
v-bind="linkProps"
|
||||
class="nav-item-link gl-rounded-base gl-relative gl-display-flex gl-align-items-center gl-mb-1 gl-px-0 gl-line-height-normal gl-text-black-normal! gl-hover-bg-t-gray-a-08 gl-focus-bg-t-gray-a-08 gl-text-decoration-none! gl-focus--focus"
|
||||
class="nav-item-link gl-rounded-base gl-relative gl-display-flex gl-align-items-center gl-min-h-7 gl-gap-3 gl-mb-1 gl-py-2 gl-text-black-normal! gl-hover-bg-t-gray-a-08 gl-focus-bg-t-gray-a-08 gl-text-decoration-none! gl-focus--focus"
|
||||
:class="computedLinkClasses"
|
||||
data-qa-selector="nav_item_link"
|
||||
data-testid="nav-item-link"
|
||||
|
|
@ -137,13 +133,13 @@ export default {
|
|||
style="width: 3px; border-radius: 3px; margin-right: 1px"
|
||||
data-testid="active-indicator"
|
||||
></div>
|
||||
<div :class="iconClasses" class="gl-flex-shrink-0">
|
||||
<div class="gl-flex-shrink-0 gl-w-6 gl-display-flex">
|
||||
<slot name="icon">
|
||||
<gl-icon v-if="item.icon" :name="item.icon" class="gl-ml-2 item-icon" />
|
||||
<gl-icon v-if="item.icon" :name="item.icon" class="gl-m-auto item-icon" />
|
||||
<gl-icon
|
||||
v-else-if="isInPinnedSection"
|
||||
name="grip"
|
||||
class="gl-text-gray-400 gl-ml-2 draggable-icon"
|
||||
class="gl-m-auto gl-text-gray-400 draggable-icon"
|
||||
/>
|
||||
</slot>
|
||||
</div>
|
||||
|
|
@ -154,7 +150,7 @@ export default {
|
|||
</div>
|
||||
</div>
|
||||
<slot name="actions"></slot>
|
||||
<span v-if="hasPill || isPinnable" class="gl-text-right gl-mr-3 gl-relative">
|
||||
<span v-if="hasPill || isPinnable" class="gl-text-right gl-relative">
|
||||
<gl-badge
|
||||
v-if="hasPill"
|
||||
size="sm"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Projects::PagesController < Projects::ApplicationController
|
||||
layout :resolve_layout
|
||||
|
||||
before_action :require_pages_enabled!
|
||||
before_action :authorize_read_pages!, only: [:show]
|
||||
before_action :authorize_update_pages!, except: [:show, :destroy]
|
||||
|
|
@ -10,10 +8,6 @@ class Projects::PagesController < Projects::ApplicationController
|
|||
|
||||
feature_category :pages
|
||||
|
||||
before_action do
|
||||
push_frontend_feature_flag(:show_pages_in_deployments_menu, current_user, type: :experiment)
|
||||
end
|
||||
|
||||
def new
|
||||
@pipeline_wizard_data = {
|
||||
project_path: @project.full_path,
|
||||
|
|
@ -66,10 +60,6 @@ class Projects::PagesController < Projects::ApplicationController
|
|||
|
||||
private
|
||||
|
||||
def resolve_layout
|
||||
'project_settings' unless Feature.enabled?(:show_pages_in_deployments_menu, current_user, type: :experiment)
|
||||
end
|
||||
|
||||
def project_params
|
||||
params.require(:project).permit(project_params_attributes)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -35,6 +35,11 @@ module Mutations
|
|||
required: false,
|
||||
description: 'Cluster agent of the environment.'
|
||||
|
||||
argument :kubernetes_namespace,
|
||||
GraphQL::Types::String,
|
||||
required: false,
|
||||
description: 'Kubernetes namespace of the environment.'
|
||||
|
||||
field :environment,
|
||||
Types::EnvironmentType,
|
||||
null: true,
|
||||
|
|
|
|||
|
|
@ -28,6 +28,11 @@ module Mutations
|
|||
required: false,
|
||||
description: 'Cluster agent of the environment.'
|
||||
|
||||
argument :kubernetes_namespace,
|
||||
GraphQL::Types::String,
|
||||
required: false,
|
||||
description: 'Kubernetes namespace of the environment.'
|
||||
|
||||
field :environment,
|
||||
Types::EnvironmentType,
|
||||
null: true,
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@ module Types
|
|||
field :external_url, GraphQL::Types::String, null: true,
|
||||
description: 'External URL of the environment.'
|
||||
|
||||
field :kubernetes_namespace, GraphQL::Types::String, null: true,
|
||||
description: 'Kubernetes namespace of the environment.'
|
||||
|
||||
field :created_at, Types::TimeType,
|
||||
description: 'When the environment was created.'
|
||||
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ module Ci
|
|||
raise FailedToPersistDataError, 'Modifed build trace chunk detected' if has_changes_to_save?
|
||||
|
||||
self.class.with_read_consistency(build) do
|
||||
reset.then(&:unsafe_persist_data!)
|
||||
reset.unsafe_persist_data!
|
||||
end
|
||||
end
|
||||
rescue FailedToObtainLockError
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class Environment < ApplicationRecord
|
|||
belongs_to :cluster_agent, class_name: 'Clusters::Agent', optional: true, inverse_of: :environments
|
||||
|
||||
use_fast_destroy :all_deployments
|
||||
nullify_if_blank :external_url
|
||||
nullify_if_blank :external_url, :kubernetes_namespace
|
||||
|
||||
has_many :all_deployments, class_name: 'Deployment'
|
||||
has_many :deployments, -> { visible }
|
||||
|
|
@ -70,6 +70,14 @@ class Environment < ApplicationRecord
|
|||
length: { maximum: 255 },
|
||||
allow_nil: true
|
||||
|
||||
validates :kubernetes_namespace,
|
||||
allow_nil: true,
|
||||
length: 1..63,
|
||||
format: {
|
||||
with: Gitlab::Regex.kubernetes_namespace_regex,
|
||||
message: Gitlab::Regex.kubernetes_namespace_regex_message
|
||||
}
|
||||
|
||||
# Currently, the tier presence is validaed for newly created environments.
|
||||
# After the `BackfillEnvironmentTiers` background migration has been completed, we should remove `on: :create`.
|
||||
# See https://gitlab.com/gitlab-org/gitlab/-/issues/385253.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
module Environments
|
||||
class CreateService < BaseService
|
||||
ALLOWED_ATTRIBUTES = %i[name external_url tier cluster_agent].freeze
|
||||
ALLOWED_ATTRIBUTES = %i[name external_url tier cluster_agent kubernetes_namespace].freeze
|
||||
|
||||
def execute
|
||||
unless can?(current_user, :create_environment, project)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
module Environments
|
||||
class UpdateService < BaseService
|
||||
ALLOWED_ATTRIBUTES = %i[external_url tier cluster_agent].freeze
|
||||
ALLOWED_ATTRIBUTES = %i[external_url tier cluster_agent kubernetes_namespace].freeze
|
||||
|
||||
def execute(environment)
|
||||
unless can?(current_user, :update_environment, environment)
|
||||
|
|
|
|||
|
|
@ -7,12 +7,10 @@
|
|||
|
||||
= render_if_exists 'shared/ultimate_feature_removal_banner', project: @project
|
||||
|
||||
- if Feature.enabled?(:show_pages_in_deployments_menu, current_user, type: :experiment)
|
||||
= render Pajamas::AlertComponent.new(variant: :info,
|
||||
title: _('GitLab Pages has moved'),
|
||||
alert_options: { class: 'gl-my-5', data: { feature_id: Users::CalloutsHelper::PAGES_MOVED_CALLOUT, dismiss_endpoint: callouts_path, defer_links: 'true' } }) do |c|
|
||||
- c.with_body do
|
||||
= _('To go to GitLab Pages, on the left sidebar, select %{pages_link}.').html_safe % {pages_link: link_to('Deployments > Pages', project_pages_path(@project)).html_safe}
|
||||
= render Pajamas::AlertComponent.new(title: _('GitLab Pages has moved'),
|
||||
alert_options: { class: 'gl-my-5', data: { feature_id: Users::CalloutsHelper::PAGES_MOVED_CALLOUT, dismiss_endpoint: callouts_path, defer_links: 'true' } }) do |c|
|
||||
- c.with_body do
|
||||
= _('To go to GitLab Pages, on the left sidebar, select %{pages_link}.').html_safe % {pages_link: link_to('Deploy > Pages', project_pages_path(@project)).html_safe}
|
||||
|
||||
%section.settings.general-settings.no-animate.expanded#js-general-settings
|
||||
.settings-header
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
- if Feature.enabled?(:show_pages_in_deployments_menu, current_user, type: :experiment)
|
||||
- @breadcrumb_link = project_pages_path(@project)
|
||||
- breadcrumb_title s_('GitLabPages|Pages')
|
||||
- page_title s_('GitLabPages|Pages')
|
||||
- else
|
||||
%section.js-search-settings-section
|
||||
- @breadcrumb_link = project_pages_path(@project)
|
||||
- page_title s_('GitLabPages|Pages')
|
||||
|
||||
- if Feature.enabled?(:use_pipeline_wizard_for_pages, @project.group)
|
||||
#js-pages{ data: @pipeline_wizard_data }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
- page_title _('Pages')
|
||||
- page_title s_('GitLabPages|Pages')
|
||||
|
||||
- unless @project.pages_deployed?
|
||||
= render 'waiting'
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: show_pages_in_deployments_menu
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97783
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/373561
|
||||
milestone: '15.4'
|
||||
type: experiment
|
||||
group: group::incubation
|
||||
default_enabled: false
|
||||
|
|
@ -53,7 +53,7 @@ Sidekiq.configure_server do |config|
|
|||
config.server_middleware(&Gitlab::SidekiqMiddleware.server_configurator(
|
||||
metrics: Settings.monitoring.sidekiq_exporter,
|
||||
arguments_logger: SidekiqLogArguments.enabled? && !enable_json_logs,
|
||||
defer_jobs: Gitlab::Utils.to_boolean(ENV['SIDEKIQ_DEFER_JOBS'], default: true)
|
||||
skip_jobs: Gitlab::Utils.to_boolean(ENV['SIDEKIQ_SKIP_JOBS'], default: true)
|
||||
))
|
||||
|
||||
config.client_middleware(&Gitlab::SidekiqMiddleware.client_configurator)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.kubernetes_agent.flux_git_push_notified_unique_projects_monthly
|
||||
description: MAU of the unique projects which were notified by agentk about new Git push events in order to reconcile their Flux workloads
|
||||
product_section: ops
|
||||
product_stage: deploy
|
||||
product_group: environment
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "16.2"
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/125146
|
||||
time_frame: 28d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
options:
|
||||
events:
|
||||
- flux_git_push_notified_unique_projects
|
||||
performance_indicator_type: []
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.kubernetes_agent.flux_git_push_notified_unique_projects_weekly
|
||||
description: WAU of the unique projects which were notified by agentk about new Git push events in order to reconcile their Flux workloads
|
||||
product_section: ops
|
||||
product_stage: deploy
|
||||
product_group: environment
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "16.2"
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/125146
|
||||
time_frame: 7d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
options:
|
||||
events:
|
||||
- flux_git_push_notified_unique_projects
|
||||
performance_indicator_type: []
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddKubernetesNamespaceColumnToEnvironments < Gitlab::Database::Migration[2.1]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
with_lock_retries do
|
||||
add_column :environments, :kubernetes_namespace, :text unless column_exists?(:environments, :kubernetes_namespace)
|
||||
end
|
||||
|
||||
add_text_limit :environments, :kubernetes_namespace, 63
|
||||
end
|
||||
|
||||
def down
|
||||
remove_column :environments, :kubernetes_namespace
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
5aa32c9cc47402adbb622bb7e8a2cd4f7714973d25a5b787c1156f3dee517433
|
||||
|
|
@ -15682,7 +15682,9 @@ CREATE TABLE environments (
|
|||
auto_delete_at timestamp with time zone,
|
||||
tier smallint,
|
||||
merge_request_id bigint,
|
||||
cluster_agent_id bigint
|
||||
cluster_agent_id bigint,
|
||||
kubernetes_namespace text,
|
||||
CONSTRAINT check_b5373a1804 CHECK ((char_length(kubernetes_namespace) <= 63))
|
||||
);
|
||||
|
||||
CREATE SEQUENCE environments_id_seq
|
||||
|
|
|
|||
|
|
@ -11,6 +11,3 @@ ignorecase: true
|
|||
link: https://docs.gitlab.com/ee/development/documentation/styleguide/index.html
|
||||
tokens:
|
||||
- '\bI[ ,;:?!"]|\bI\x27.{1,2}'
|
||||
- me
|
||||
- myself
|
||||
- mine
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ configuration option in `gitlab.yml`. These metrics are served from the
|
|||
| `sidekiq_jobs_dead_total` | Counter | 13.7 | Sidekiq dead jobs (jobs that have run out of retries) | `queue`, `boundary`, `external_dependencies`, `feature_category`, `urgency` |
|
||||
| `sidekiq_redis_requests_total` | Counter | 13.1 | Redis requests during a Sidekiq job execution | `queue`, `boundary`, `external_dependencies`, `feature_category`, `job_status`, `urgency` |
|
||||
| `sidekiq_elasticsearch_requests_total` | Counter | 13.1 | Elasticsearch requests during a Sidekiq job execution | `queue`, `boundary`, `external_dependencies`, `feature_category`, `job_status`, `urgency` |
|
||||
| `sidekiq_jobs_deferred_total` | Counter | 16.1 | Number of jobs being deferred (either via `run_sidekiq_jobs` feature flag or DB health status indicator) | `worker` |
|
||||
| `sidekiq_jobs_skipped_total` | Counter | 16.2 | Number of jobs being skipped (dropped or deferred) when `drop_sidekiq_jobs` feature flag is enabled or `run_sidekiq_jobs` feature flag is disabled | `worker`, `action` |
|
||||
| `sidekiq_running_jobs` | Gauge | 12.2 | Number of Sidekiq jobs running | `queue`, `boundary`, `external_dependencies`, `feature_category`, `urgency` |
|
||||
| `sidekiq_concurrency` | Gauge | 12.5 | Maximum number of Sidekiq jobs | |
|
||||
| `sidekiq_mem_total_bytes` | Gauge | 15.3 | Number of bytes allocated for both objects consuming an object slot and objects that required a malloc'| |
|
||||
|
|
|
|||
|
|
@ -719,10 +719,7 @@ Prerequisite:
|
|||
To set the maximum size of GitLab Pages site in a project, overriding the inherited setting:
|
||||
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. On the left sidebar, select **Settings > Pages**.
|
||||
|
||||
If this path is not visible, select **Deployments > Pages**.
|
||||
[This location is part of an experiment](../../user/project/pages/index.md#menu-position-test).
|
||||
1. On the left sidebar, select **Deploy > Pages**.
|
||||
1. In **Maximum size of pages**, enter the size in MB.
|
||||
1. Select **Save changes**.
|
||||
|
||||
|
|
|
|||
|
|
@ -3183,6 +3183,7 @@ Input type: `EnvironmentCreateInput`
|
|||
| <a id="mutationenvironmentcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationenvironmentcreateclusteragentid"></a>`clusterAgentId` | [`ClustersAgentID`](#clustersagentid) | Cluster agent of the environment. |
|
||||
| <a id="mutationenvironmentcreateexternalurl"></a>`externalUrl` | [`String`](#string) | External URL of the environment. |
|
||||
| <a id="mutationenvironmentcreatekubernetesnamespace"></a>`kubernetesNamespace` | [`String`](#string) | Kubernetes namespace of the environment. |
|
||||
| <a id="mutationenvironmentcreatename"></a>`name` | [`String!`](#string) | Name of the environment. |
|
||||
| <a id="mutationenvironmentcreateprojectpath"></a>`projectPath` | [`ID!`](#id) | Full path of the project. |
|
||||
| <a id="mutationenvironmentcreatetier"></a>`tier` | [`DeploymentTier`](#deploymenttier) | Tier of the environment. |
|
||||
|
|
@ -3251,6 +3252,7 @@ Input type: `EnvironmentUpdateInput`
|
|||
| <a id="mutationenvironmentupdateclusteragentid"></a>`clusterAgentId` | [`ClustersAgentID`](#clustersagentid) | Cluster agent of the environment. |
|
||||
| <a id="mutationenvironmentupdateexternalurl"></a>`externalUrl` | [`String`](#string) | External URL of the environment. |
|
||||
| <a id="mutationenvironmentupdateid"></a>`id` | [`EnvironmentID!`](#environmentid) | Global ID of the environment to update. |
|
||||
| <a id="mutationenvironmentupdatekubernetesnamespace"></a>`kubernetesNamespace` | [`String`](#string) | Kubernetes namespace of the environment. |
|
||||
| <a id="mutationenvironmentupdatetier"></a>`tier` | [`DeploymentTier`](#deploymenttier) | Tier of the environment. |
|
||||
|
||||
#### Fields
|
||||
|
|
@ -14772,6 +14774,7 @@ Describes where code is deployed for a project.
|
|||
| <a id="environmentenvironmenttype"></a>`environmentType` | [`String`](#string) | Folder name of the environment. |
|
||||
| <a id="environmentexternalurl"></a>`externalUrl` | [`String`](#string) | External URL of the environment. |
|
||||
| <a id="environmentid"></a>`id` | [`ID!`](#id) | ID of the environment. |
|
||||
| <a id="environmentkubernetesnamespace"></a>`kubernetesNamespace` | [`String`](#string) | Kubernetes namespace of the environment. |
|
||||
| <a id="environmentlatestopenedmostseverealert"></a>`latestOpenedMostSevereAlert` | [`AlertManagementAlert`](#alertmanagementalert) | Most severe open alert for the environment. If multiple alerts have equal severity, the most recent is returned. |
|
||||
| <a id="environmentname"></a>`name` | [`String!`](#string) | Human-readable name of the environment. |
|
||||
| <a id="environmentpath"></a>`path` | [`String!`](#string) | Path to the environment. |
|
||||
|
|
|
|||
|
|
@ -693,7 +693,7 @@ Instead of:
|
|||
|
||||
## I
|
||||
|
||||
Do not use first-person singular. Use **you**, **we**, or **us** instead. ([Vale](../testing.md#vale) rule: [`FirstPerson.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FirstPerson.yml))
|
||||
Do not use first-person singular. Use **you** or rewrite the phrase instead. ([Vale](../testing.md#vale) rule: [`FirstPerson.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FirstPerson.yml))
|
||||
|
||||
## i.e.
|
||||
|
||||
|
|
@ -897,10 +897,6 @@ Instead of:
|
|||
|
||||
For **MB** and **GB**, follow the [Microsoft guidance](https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/term-collections/bits-bytes-terms).
|
||||
|
||||
## me, myself, mine
|
||||
|
||||
Do not use first-person singular. Use **you**, **we**, or **us** instead. ([Vale](../testing.md#vale) rule: [`FirstPerson.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FirstPerson.yml))
|
||||
|
||||
## member
|
||||
|
||||
When you add a [user account](#user-account) to a group or project,
|
||||
|
|
|
|||
|
|
@ -717,10 +717,10 @@ When disabled, feature flags with the format of `run_sidekiq_jobs_{WorkerName}`
|
|||
by scheduling the job at a later time. This feature flag is enabled by default for all workers.
|
||||
Deferring jobs can be useful during an incident where contentious behavior from
|
||||
worker instances are saturating infrastructure resources (such as database and database connection pool).
|
||||
The implementation can be found at [DeferJobs Sidekiq server middleware](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/sidekiq_middleware/defer_jobs.rb).
|
||||
The implementation can be found at [SkipJobs Sidekiq server middleware](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/sidekiq_middleware/skip_jobs.rb).
|
||||
|
||||
NOTE:
|
||||
Jobs are deferred indefinitely as long as the feature flag is disabled. It is important to enable the
|
||||
Jobs are deferred indefinitely as long as the feature flag is disabled. It is important to remove the
|
||||
feature flag after the worker is deemed safe to continue processing.
|
||||
|
||||
When set to false, 100% of the jobs are deferred. When you want processing to resume, you can
|
||||
|
|
@ -737,5 +737,23 @@ use a **percentage of time** rollout. For example:
|
|||
/chatops run feature set run_sidekiq_jobs_SlowRunningWorker 50
|
||||
|
||||
# back to running all jobs normally
|
||||
/chatops run feature set run_sidekiq_jobs_SlowRunningWorker true
|
||||
/chatops run feature delete run_sidekiq_jobs_SlowRunningWorker
|
||||
```
|
||||
|
||||
### Dropping Sidekiq jobs
|
||||
|
||||
Instead of [deferring jobs](#deferring-sidekiq-jobs), jobs can be entirely dropped by enabling the feature flag
|
||||
`drop_sidekiq_jobs_{WorkerName}`. Use this feature flag when you are certain the jobs are safe to be dropped, i.e.
|
||||
the jobs do not need to be processed in the future.
|
||||
|
||||
```shell
|
||||
# drop all the jobs
|
||||
/chatops run feature set drop_sidekiq_jobs_SlowRunningWorker true
|
||||
|
||||
# process jobs normally
|
||||
/chatops run feature delete drop_sidekiq_jobs_SlowRunningWorker
|
||||
```
|
||||
|
||||
NOTE:
|
||||
Dropping feature flag (`drop_sidekiq_jobs_{WorkerName}`) takes precedence over deferring feature flag (`run_sidekiq_jobs_{WorkerName}`),
|
||||
i.e. when `drop_sidekiq_jobs` is enabled and `run_sidekiq_jobs` is disabled, jobs are entirely dropped.
|
||||
|
|
|
|||
|
|
@ -506,6 +506,7 @@ metric counters.
|
|||
| `unique_counters["k8s_api_proxy_requests_unique_agents_via_ci_access"]` | integer array | no | The set of unique user ids that have interacted a CI Tunnel via `ci_access` to track the `k8s_api_proxy_requests_unique_agents_via_ci_access` metric event |
|
||||
| `unique_counters["k8s_api_proxy_requests_unique_users_via_user_access"]` | integer array | no | The set of unique user ids that have interacted a CI Tunnel via `user_access` to track the `k8s_api_proxy_requests_unique_users_via_user_access` metric event |
|
||||
| `unique_counters["k8s_api_proxy_requests_unique_agents_via_user_access"]` | integer array | no | The set of unique user ids that have interacted a CI Tunnel via `user_access` to track the `k8s_api_proxy_requests_unique_agents_via_user_access` metric event |
|
||||
| `unique_counters["flux_git_push_notified_unique_projects"]` | integer array | no | The set of unique projects ids that have been notified to reconcile their Flux workloads to track the `flux_git_push_notified_unique_projects` metric event |
|
||||
|
||||
```plaintext
|
||||
POST /internal/kubernetes/usage_metrics
|
||||
|
|
|
|||
|
|
@ -54,10 +54,7 @@ this document for an [overview on DNS records](dns_concepts.md).
|
|||
To add your custom domain to GitLab Pages:
|
||||
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. Select **Settings > Pages**.
|
||||
|
||||
If this path is not visible, select **Deployments > Pages**.
|
||||
[This location is part of an experiment](../index.md#menu-position-test).
|
||||
1. On the left sidebar, select **Deploy > Pages**.
|
||||
1. In the upper-right corner, select **New Domain**.
|
||||
1. In **Domain**, enter the domain name.
|
||||
1. Optional. In **Certificate**, turn off the **Automatic certificate management using Let's Encrypt** toggle to add an [SSL/TLS certificate](#adding-an-ssltls-certificate-to-pages). You can also add the certificate and key later.
|
||||
|
|
@ -168,10 +165,7 @@ If you're using Cloudflare, check
|
|||
After you have added all the DNS records:
|
||||
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. Select **Settings > Pages**.
|
||||
|
||||
If this path is not visible, select **Deployments > Pages**.
|
||||
[This location is part of an experiment](../index.md#menu-position-test).
|
||||
1. On the left sidebar, select **Deploy > Pages**.
|
||||
1. Next to the domain name, select **Edit**.
|
||||
1. In **Verification status**, select **Retry verification** (**{retry}**).
|
||||
|
||||
|
|
@ -263,10 +257,7 @@ meet these requirements.
|
|||
- To add the certificate at the time you add a new domain:
|
||||
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. Select **Settings > Pages**.
|
||||
|
||||
If this path is not visible, select **Deployments > Pages**.
|
||||
[This location is part of an experiment](../index.md#menu-position-test).
|
||||
1. On the left sidebar, select **Deploy > Pages**.
|
||||
1. In the upper-right corner, select **New Domain**.
|
||||
1. In **Domain**, enter the domain name.
|
||||
1. In **Certificate**, turn off the **Automatic certificate management using Let's Encrypt** toggle to add an [SSL/TLS certificate](#adding-an-ssltls-certificate-to-pages).
|
||||
|
|
@ -275,17 +266,11 @@ meet these requirements.
|
|||
- To add the certificate to a domain previously added:
|
||||
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. Select **Settings > Pages**.
|
||||
|
||||
If this path is not visible, select **Deployments > Pages**.
|
||||
[This location is part of an experiment](../index.md#menu-position-test).
|
||||
1. On the left sidebar, select **Deploy > Pages**.
|
||||
1. Next to the domain name, select **Edit**.
|
||||
1. In **Certificate**, turn off the **Automatic certificate management using Let's Encrypt** toggle to add an [SSL/TLS certificate](#adding-an-ssltls-certificate-to-pages).
|
||||
1. Select **Save changes**.
|
||||
|
||||
NOTE:
|
||||
The Pages menu entry may also be located at **Deployments > Pages**, [more information](../index.md#menu-position-test)
|
||||
|
||||
1. Add the PEM certificate to its corresponding field.
|
||||
1. If your certificate is missing its intermediate, copy
|
||||
and paste the root certificate (usually available from your CA website)
|
||||
|
|
@ -309,10 +294,7 @@ domain (as long as you've set a valid certificate for it).
|
|||
To enable this setting:
|
||||
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. Select **Settings > Pages**.
|
||||
|
||||
If this path is not visible, select **Deployments > Pages**.
|
||||
[This location is part of an experiment](../index.md#menu-position-test).
|
||||
1. On the left sidebar, select **Deploy > Pages**.
|
||||
1. Select the **Force HTTPS (requires valid certificates)** checkbox.
|
||||
1. Select **Save changes**.
|
||||
|
||||
|
|
|
|||
|
|
@ -43,10 +43,7 @@ For **self-managed** GitLab instances, make sure your administrator has
|
|||
Once you've met the requirements, enable Let's Encrypt integration:
|
||||
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. Select **Settings > Pages**.
|
||||
|
||||
If this path is not visible, select **Deployments > Pages**.
|
||||
[This location is part of an experiment](../index.md#menu-position-test).
|
||||
1. On the left sidebar, select **Deploy > Pages**.
|
||||
1. Next to the domain name, select **Edit**.
|
||||
1. Turn on the **Automatic certificate management using Let's Encrypt** toggle.
|
||||
|
||||
|
|
@ -73,10 +70,7 @@ associated Pages domain. GitLab also renews it automatically.
|
|||
If you get an error **Something went wrong while obtaining the Let's Encrypt certificate**, first, make sure that your pages site is set to "Everyone" in your project's **Settings > General > Visibility**. This allows the Let's Encrypt Servers reach your pages site. Once this is confirmed, you can try obtaining the certificate again by following these steps:
|
||||
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. Select **Settings > Pages**.
|
||||
|
||||
If this path is not visible, select **Deployments > Pages**.
|
||||
[This location is part of an experiment](../index.md#menu-position-test).
|
||||
1. On the left sidebar, select **Deploy > Pages**.
|
||||
1. Next to the domain name, select **Edit**.
|
||||
1. In **Verification status**, select **Retry verification** (**{retry}**).
|
||||
1. If you're still getting the same error:
|
||||
|
|
@ -91,10 +85,7 @@ If you get an error **Something went wrong while obtaining the Let's Encrypt cer
|
|||
If you've enabled Let's Encrypt integration, but a certificate is absent after an hour and you see the message, "GitLab is obtaining a Let's Encrypt SSL certificate for this domain. This process can take some time. Please try again later.", try to remove and add the domain for GitLab Pages again by following these steps:
|
||||
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. Select **Settings > Pages**.
|
||||
|
||||
If this path is not visible, select **Deployments > Pages**.
|
||||
[This location is part of an experiment](../index.md#menu-position-test).
|
||||
1. On the left sidebar, select **Deploy > Pages**.
|
||||
1. Next to the domain name, select **Remove**.
|
||||
1. [Add the domain again, and verify it](index.md#1-add-a-custom-domain).
|
||||
1. [Enable Let's Encrypt integration for your domain](#enabling-lets-encrypt-integration-for-your-custom-domain).
|
||||
|
|
|
|||
|
|
@ -27,10 +27,8 @@ If everything is configured correctly, the site can take approximately 30 minute
|
|||
|
||||
To view the pipeline, go to **CI/CD > Pipelines**.
|
||||
|
||||
When the pipeline is finished, go to **Settings > Pages** to find the link to
|
||||
When the pipeline is finished, go to **Deploy > Pages** to find the link to
|
||||
your Pages website.
|
||||
If this path is not visible, select **Deployments > Pages**.
|
||||
[This location is part of an experiment](../index.md#menu-position-test).
|
||||
|
||||
For every change pushed to your repository, GitLab CI/CD runs a new pipeline
|
||||
that immediately publishes your changes to the Pages site.
|
||||
|
|
|
|||
|
|
@ -24,10 +24,8 @@ To fork a sample project and create a Pages website:
|
|||
GitLab CI/CD builds and deploys your site.
|
||||
|
||||
The site can take approximately 30 minutes to deploy.
|
||||
When the pipeline is finished, go to **Settings > Pages** to find the link to
|
||||
When the pipeline is finished, go to **Deploy > Pages** to find the link to
|
||||
your Pages website.
|
||||
If this path is not visible, select **Deployments > Pages**.
|
||||
[This location is part of an experiment](../index.md#menu-position-test).
|
||||
|
||||
For every change pushed to your repository, GitLab CI/CD runs a new pipeline
|
||||
that immediately publishes your changes to the Pages site.
|
||||
|
|
|
|||
|
|
@ -175,11 +175,9 @@ deploy your website:
|
|||
|
||||
1. Save and commit the `.gitlab-ci.yml` file.
|
||||
1. Go to **CI/CD > Pipelines** to watch the pipeline.
|
||||
1. When the pipeline is finished, go to **Settings > Pages** to find the link to
|
||||
1. When the pipeline is finished, go to **Deploy > Pages** to find the link to
|
||||
your Pages website.
|
||||
|
||||
If this path is not visible, select **Deployments > Pages**.
|
||||
[This location is part of an experiment](../index.md#menu-position-test).
|
||||
When this `pages` job completes successfully, a special `pages:deploy` job
|
||||
appears in the pipeline view. It prepares the content of the website for the
|
||||
GitLab Pages daemon. GitLab runs it in the background and doesn't use a runner.
|
||||
|
|
|
|||
|
|
@ -23,10 +23,8 @@ configured to generate a Pages site.
|
|||
and select **Run pipeline** to trigger GitLab CI/CD to build and deploy your
|
||||
site.
|
||||
|
||||
When the pipeline is finished, go to **Settings > Pages** to find the link to
|
||||
When the pipeline is finished, go to **Deploy > Pages** to find the link to
|
||||
your Pages website.
|
||||
If this path is not visible, select **Deployments > Pages**.
|
||||
[This location is part of an experiment](../index.md#menu-position-test).
|
||||
|
||||
For every change pushed to your repository, GitLab CI/CD runs a new pipeline
|
||||
that immediately publishes your changes to the Pages site.
|
||||
|
|
|
|||
|
|
@ -34,10 +34,8 @@ a pipeline deploys your Pages website.
|
|||
To complete the setup and generate a GitLab Pages deployment:
|
||||
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. Select **Settings > Pages**.
|
||||
1. On the left sidebar, select **Deploy > Pages**.
|
||||
|
||||
If this path is not visible, select **Deployments > Pages**.
|
||||
[This location is part of an experiment](../index.md#menu-position-test).
|
||||
A **Get Started with Pages** form appears. If this form is not available,
|
||||
see [Troubleshooting](#if-the-get-started-with-pages-form-is-not-available).
|
||||
1. For **Step 1**, enter an image name and verify that your files are in a `public` folder.
|
||||
|
|
|
|||
|
|
@ -34,13 +34,6 @@ Pages does not support dynamic server-side processing, for instance, as `.php` a
|
|||
For more information, see
|
||||
[Static vs dynamic websites](https://about.gitlab.com/blog/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/).
|
||||
|
||||
## Menu Position Test
|
||||
|
||||
NOTE:
|
||||
We are currently conducting an A/B test where some users may see the Pages
|
||||
Menu entry under "Deployments" instead of "Settings". We think that this may
|
||||
be a more accurate position. Feel free to add any feedback to [the experiment issue](https://gitlab.com/gitlab-org/gitlab/-/issues/373547).
|
||||
|
||||
## Getting started
|
||||
|
||||
To create a GitLab Pages website:
|
||||
|
|
|
|||
|
|
@ -65,10 +65,7 @@ You can configure redirects for your site using a `_redirects` file. For more in
|
|||
To remove your pages:
|
||||
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. Select **Settings > Pages**.
|
||||
|
||||
If this path is not visible, select **Deployments > Pages**.
|
||||
[This location is part of an experiment](index.md#menu-position-test).
|
||||
1. On the left sidebar, select **Deploy > Pages**.
|
||||
1. Select **Remove pages**.
|
||||
|
||||
## Subdomains of subdomains
|
||||
|
|
@ -102,7 +99,7 @@ By default, every project in a group shares the same domain, for example, `group
|
|||
To ensure your project uses a unique Pages domain, enable the unique domains feature for the project:
|
||||
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. Select **Settings > Pages**.
|
||||
1. On the left sidebar, select **Deploy > Pages**.
|
||||
1. Select the **Use unique domain** checkbox.
|
||||
1. Select **Save changes**.
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,8 @@ module API
|
|||
events = params[:unique_counters]&.slice(
|
||||
:agent_users_using_ci_tunnel,
|
||||
:k8s_api_proxy_requests_unique_users_via_ci_access, :k8s_api_proxy_requests_unique_agents_via_ci_access,
|
||||
:k8s_api_proxy_requests_unique_users_via_user_access, :k8s_api_proxy_requests_unique_agents_via_user_access
|
||||
:k8s_api_proxy_requests_unique_users_via_user_access, :k8s_api_proxy_requests_unique_agents_via_user_access,
|
||||
:flux_git_push_notified_unique_projects
|
||||
)
|
||||
|
||||
events&.each do |event, entity_ids|
|
||||
|
|
@ -220,6 +221,7 @@ module API
|
|||
optional :k8s_api_proxy_requests_unique_agents_via_ci_access, type: Array[Integer], desc: 'An array of agents that have interacted with the CI tunnel via `ci_access`'
|
||||
optional :k8s_api_proxy_requests_unique_users_via_user_access, type: Array[Integer], desc: 'An array of users that have interacted with the CI tunnel via `user_access`'
|
||||
optional :k8s_api_proxy_requests_unique_agents_via_user_access, type: Array[Integer], desc: 'An array of agents that have interacted with the CI tunnel via `user_access`'
|
||||
optional :flux_git_push_notified_unique_projects, type: Array[Integer], desc: 'An array of projects that have been notified to reconcile their Flux workloads'
|
||||
end
|
||||
end
|
||||
post '/', feature_category: :deployment_management do
|
||||
|
|
|
|||
|
|
@ -78,6 +78,8 @@ module Gitlab
|
|||
|
||||
job_status = if job_exception
|
||||
'fail'
|
||||
elsif job['dropped']
|
||||
'dropped'
|
||||
elsif job['deferred']
|
||||
'deferred'
|
||||
else
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ module Gitlab
|
|||
# The result of this method should be passed to
|
||||
# Sidekiq's `config.server_middleware` method
|
||||
# eg: `config.server_middleware(&Gitlab::SidekiqMiddleware.server_configurator)`
|
||||
def self.server_configurator(metrics: true, arguments_logger: true, defer_jobs: true)
|
||||
def self.server_configurator(metrics: true, arguments_logger: true, skip_jobs: true)
|
||||
lambda do |chain|
|
||||
# Size limiter should be placed at the top
|
||||
chain.add ::Gitlab::SidekiqMiddleware::SizeLimiter::Server
|
||||
|
|
@ -40,7 +40,7 @@ module Gitlab
|
|||
# so we can compare the latest WAL location against replica
|
||||
chain.add ::Gitlab::SidekiqMiddleware::DuplicateJobs::Server
|
||||
chain.add ::Gitlab::Database::LoadBalancing::SidekiqServerMiddleware
|
||||
chain.add ::Gitlab::SidekiqMiddleware::DeferJobs if defer_jobs
|
||||
chain.add ::Gitlab::SidekiqMiddleware::SkipJobs if skip_jobs
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,89 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module SidekiqMiddleware
|
||||
class DeferJobs
|
||||
DELAY = ENV.fetch("SIDEKIQ_DEFER_JOBS_DELAY", 5.minutes)
|
||||
RUN_FEATURE_FLAG_PREFIX = "run_sidekiq_jobs"
|
||||
|
||||
DatabaseHealthStatusChecker = Struct.new(:id, :job_class_name)
|
||||
|
||||
DEFERRED_COUNTER = :sidekiq_jobs_deferred_total
|
||||
|
||||
def initialize
|
||||
@metrics = init_metrics
|
||||
end
|
||||
|
||||
# There are 2 scenarios under which this middleware defers a job
|
||||
# 1. When run_sidekiq_jobs_#{worker_name} FF is disabled. This FF is enabled by default
|
||||
# for all workers.
|
||||
# 2. Gitlab::Database::HealthStatus, on evaluating the db health status if it returns any indicator
|
||||
# with stop signal, the jobs will be delayed by 'x' seconds (set in worker).
|
||||
def call(worker, job, _queue)
|
||||
# ActiveJobs have wrapped class stored in 'wrapped' key
|
||||
resolved_class = job['wrapped']&.safe_constantize || worker.class
|
||||
defer_job, delay, deferred_by = defer_job_info(resolved_class, job)
|
||||
|
||||
if !!defer_job
|
||||
# Referred in job_logger's 'log_job_done' method to compute proper 'job_status'
|
||||
job['deferred'] = true
|
||||
job['deferred_by'] = deferred_by
|
||||
job['deferred_count'] ||= 0
|
||||
job['deferred_count'] += 1
|
||||
|
||||
worker.class.perform_in(delay, *job['args'])
|
||||
@metrics.fetch(DEFERRED_COUNTER).increment({ worker: worker.class.name })
|
||||
|
||||
# This breaks the middleware chain and return
|
||||
return
|
||||
end
|
||||
|
||||
yield
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def defer_job_info(worker_class, job)
|
||||
if !run_job_by_ff?(worker_class)
|
||||
[true, DELAY, :feature_flag]
|
||||
elsif defer_job_by_database_health_signal?(job, worker_class)
|
||||
[true, worker_class.database_health_check_attrs[:delay_by], :database_health_check]
|
||||
end
|
||||
end
|
||||
|
||||
def run_job_by_ff?(worker_class)
|
||||
# always returns true by default for all workers unless the FF is specifically disabled, e.g. during an incident
|
||||
Feature.enabled?(
|
||||
:"#{RUN_FEATURE_FLAG_PREFIX}_#{worker_class.name}",
|
||||
type: :worker,
|
||||
default_enabled_if_undefined: true
|
||||
)
|
||||
end
|
||||
|
||||
def defer_job_by_database_health_signal?(job, worker_class)
|
||||
unless worker_class.respond_to?(:defer_on_database_health_signal?) &&
|
||||
worker_class.defer_on_database_health_signal?
|
||||
return false
|
||||
end
|
||||
|
||||
health_check_attrs = worker_class.database_health_check_attrs
|
||||
job_base_model = Gitlab::Database.schemas_to_base_models[health_check_attrs[:gitlab_schema]].first
|
||||
|
||||
health_context = Gitlab::Database::HealthStatus::Context.new(
|
||||
DatabaseHealthStatusChecker.new(job['jid'], worker_class.name),
|
||||
job_base_model.connection,
|
||||
health_check_attrs[:gitlab_schema],
|
||||
health_check_attrs[:tables]
|
||||
)
|
||||
|
||||
Gitlab::Database::HealthStatus.evaluate(health_context).any?(&:stop?)
|
||||
end
|
||||
|
||||
def init_metrics
|
||||
{
|
||||
DEFERRED_COUNTER => Gitlab::Metrics.counter(DEFERRED_COUNTER, 'The number of jobs deferred')
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module SidekiqMiddleware
|
||||
class SkipJobs
|
||||
DELAY = ENV.fetch("SIDEKIQ_DEFER_JOBS_DELAY", 5.minutes)
|
||||
RUN_FEATURE_FLAG_PREFIX = "run_sidekiq_jobs"
|
||||
DROP_FEATURE_FLAG_PREFIX = "drop_sidekiq_jobs"
|
||||
|
||||
DatabaseHealthStatusChecker = Struct.new(:id, :job_class_name)
|
||||
|
||||
COUNTER = :sidekiq_jobs_skipped_total
|
||||
|
||||
def initialize
|
||||
@metrics = init_metrics
|
||||
end
|
||||
|
||||
# This middleware decides whether a job is dropped, deferred or runs normally.
|
||||
# In short:
|
||||
# - `drop_sidekiq_jobs_#{worker_name}` FF enabled (disabled by default) --> drops the job
|
||||
# - `run_sidekiq_jobs_#{worker_name}` FF disabled (enabled by default) --> defers the job
|
||||
#
|
||||
# DROPPING JOBS
|
||||
# A job is dropped when `drop_sidekiq_jobs_#{worker_name}` FF is enabled. This FF is disabled by default for
|
||||
# all workers. Dropped jobs are completely ignored and not requeued for future processing.
|
||||
#
|
||||
# DEFERRING JOBS
|
||||
# Deferred jobs are rescheduled to perform in the future.
|
||||
# There are 2 scenarios under which this middleware defers a job:
|
||||
# 1. When run_sidekiq_jobs_#{worker_name} FF is disabled. This FF is enabled by default
|
||||
# for all workers.
|
||||
# 2. Gitlab::Database::HealthStatus, on evaluating the db health status if it returns any indicator
|
||||
# with stop signal, the jobs will be delayed by 'x' seconds (set in worker).
|
||||
#
|
||||
# Dropping jobs takes higher priority over deferring jobs. For example, when `drop_sidekiq_jobs` is enabled and
|
||||
# `run_sidekiq_jobs` is disabled, it results to jobs being dropped.
|
||||
def call(worker, job, _queue)
|
||||
# ActiveJobs have wrapped class stored in 'wrapped' key
|
||||
resolved_class = job['wrapped']&.safe_constantize || worker.class
|
||||
if drop_job?(resolved_class)
|
||||
# no-op, drop the job entirely
|
||||
drop_job!(job, worker)
|
||||
return
|
||||
elsif !!defer_job?(resolved_class, job)
|
||||
defer_job!(job, worker)
|
||||
return
|
||||
end
|
||||
|
||||
yield
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def defer_job?(worker_class, job)
|
||||
if !run_job_by_ff?(worker_class)
|
||||
@delay = DELAY
|
||||
@deferred_by = :feature_flag
|
||||
true
|
||||
elsif defer_job_by_database_health_signal?(job, worker_class)
|
||||
@delay = worker_class.database_health_check_attrs[:delay_by]
|
||||
@deferred_by = :database_health_check
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
def run_job_by_ff?(worker_class)
|
||||
# always returns true by default for all workers unless the FF is specifically disabled, e.g. during an incident
|
||||
Feature.enabled?(
|
||||
:"#{RUN_FEATURE_FLAG_PREFIX}_#{worker_class.name}",
|
||||
type: :worker,
|
||||
default_enabled_if_undefined: true
|
||||
)
|
||||
end
|
||||
|
||||
def defer_job_by_database_health_signal?(job, worker_class)
|
||||
unless worker_class.respond_to?(:defer_on_database_health_signal?) &&
|
||||
worker_class.defer_on_database_health_signal?
|
||||
return false
|
||||
end
|
||||
|
||||
health_check_attrs = worker_class.database_health_check_attrs
|
||||
job_base_model = Gitlab::Database.schemas_to_base_models[health_check_attrs[:gitlab_schema]].first
|
||||
|
||||
health_context = Gitlab::Database::HealthStatus::Context.new(
|
||||
DatabaseHealthStatusChecker.new(job['jid'], worker_class.name),
|
||||
job_base_model.connection,
|
||||
health_check_attrs[:gitlab_schema],
|
||||
health_check_attrs[:tables]
|
||||
)
|
||||
|
||||
Gitlab::Database::HealthStatus.evaluate(health_context).any?(&:stop?)
|
||||
end
|
||||
|
||||
def drop_job?(worker_class)
|
||||
Feature.enabled?(
|
||||
:"#{DROP_FEATURE_FLAG_PREFIX}_#{worker_class.name}",
|
||||
type: :worker,
|
||||
default_enabled_if_undefined: false
|
||||
)
|
||||
end
|
||||
|
||||
def drop_job!(job, worker)
|
||||
job['dropped'] = true
|
||||
@metrics.fetch(COUNTER).increment({ worker: worker.class.name, action: "dropped" })
|
||||
end
|
||||
|
||||
def defer_job!(job, worker)
|
||||
# Referred in job_logger's 'log_job_done' method to compute proper 'job_status'
|
||||
job['deferred'] = true
|
||||
job['deferred_by'] = @deferred_by
|
||||
job['deferred_count'] ||= 0
|
||||
job['deferred_count'] += 1
|
||||
|
||||
worker.class.perform_in(@delay, *job['args'])
|
||||
@metrics.fetch(COUNTER).increment({ worker: worker.class.name, action: "deferred" })
|
||||
end
|
||||
|
||||
def init_metrics
|
||||
{
|
||||
COUNTER => Gitlab::Metrics.counter(COUNTER, 'The number of skipped jobs')
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -16,3 +16,7 @@
|
|||
aggregation: weekly
|
||||
- name: k8s_api_proxy_requests_unique_agents_via_user_access
|
||||
aggregation: monthly
|
||||
- name: flux_git_push_notified_unique_projects
|
||||
aggregation: weekly
|
||||
- name: flux_git_push_notified_unique_projects
|
||||
aggregation: monthly
|
||||
|
|
|
|||
|
|
@ -9,10 +9,7 @@ module Sidebars
|
|||
add_item(environments_menu_item)
|
||||
add_item(feature_flags_menu_item)
|
||||
add_item(releases_menu_item)
|
||||
|
||||
if Feature.enabled?(:show_pages_in_deployments_menu, context.current_user, type: :experiment)
|
||||
add_item(pages_menu_item)
|
||||
end
|
||||
add_item(pages_menu_item)
|
||||
|
||||
true
|
||||
end
|
||||
|
|
@ -95,8 +92,8 @@ module Sidebars
|
|||
::Sidebars::MenuItem.new(
|
||||
title: _('Pages'),
|
||||
link: project_pages_path(context.project),
|
||||
super_sidebar_parent: Sidebars::Projects::SuperSidebarMenus::OperationsMenu,
|
||||
active_routes: { path: 'pages#show' },
|
||||
super_sidebar_parent: Sidebars::Projects::SuperSidebarMenus::DeployMenu,
|
||||
active_routes: { path: %w[pages#new pages#show] },
|
||||
item_id: :pages
|
||||
)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -16,11 +16,6 @@ module Sidebars
|
|||
add_item(merge_requests_menu_item)
|
||||
add_item(ci_cd_menu_item)
|
||||
add_item(packages_and_registries_menu_item)
|
||||
|
||||
if Feature.disabled?(:show_pages_in_deployments_menu, context.current_user, type: :experiment)
|
||||
add_item(pages_menu_item)
|
||||
end
|
||||
|
||||
add_item(monitor_menu_item)
|
||||
add_item(usage_quotas_menu_item)
|
||||
|
||||
|
|
@ -131,19 +126,6 @@ module Sidebars
|
|||
)
|
||||
end
|
||||
|
||||
def pages_menu_item
|
||||
unless context.project.pages_available?
|
||||
return ::Sidebars::NilMenuItem.new(item_id: :pages)
|
||||
end
|
||||
|
||||
::Sidebars::MenuItem.new(
|
||||
title: _('Pages'),
|
||||
link: project_pages_path(context.project),
|
||||
active_routes: { path: 'pages#show' },
|
||||
item_id: :pages
|
||||
)
|
||||
end
|
||||
|
||||
def monitor_menu_item
|
||||
if context.project.archived? || !can?(context.current_user, :admin_operations, context.project)
|
||||
return ::Sidebars::NilMenuItem.new(item_id: :monitor)
|
||||
|
|
|
|||
|
|
@ -4596,6 +4596,9 @@ msgstr ""
|
|||
msgid "All changes are committed"
|
||||
msgstr ""
|
||||
|
||||
msgid "All default branches"
|
||||
msgstr ""
|
||||
|
||||
msgid "All eligible users"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -30,9 +30,6 @@ module QA
|
|||
end
|
||||
|
||||
before do
|
||||
# Pages Menu Experiment currently progress https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98044
|
||||
# Update spec along with Feature Flag Removal.
|
||||
Runtime::Feature.disable(:show_pages_in_deployments_menu)
|
||||
Flow::Login.sign_in
|
||||
Resource::ProjectRunner.fabricate_via_api! do |runner|
|
||||
runner.project = project
|
||||
|
|
@ -41,10 +38,6 @@ module QA
|
|||
pipeline.visit!
|
||||
end
|
||||
|
||||
after do
|
||||
Runtime::Feature.enable(:show_pages_in_deployments_menu)
|
||||
end
|
||||
|
||||
it 'creates a Pages website',
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347669' do
|
||||
Page::Project::Pipeline::Show.perform do |show|
|
||||
|
|
@ -57,7 +50,7 @@ module QA
|
|||
end
|
||||
|
||||
Page::Project::Menu.perform(&:go_to_pages_settings)
|
||||
Page::Project::Settings::Pages.perform(&:go_to_access_page)
|
||||
Page::Project::Deployments::Pages.perform(&:go_to_access_page)
|
||||
|
||||
Support::Waiter.wait_until(
|
||||
sleep_interval: 2,
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@ RSpec.describe 'Project navbar', :with_license, feature_category: :groups_and_pr
|
|||
before do
|
||||
sign_in(user)
|
||||
|
||||
stub_feature_flags(show_pages_in_deployments_menu: false)
|
||||
|
||||
stub_config(registry: { enabled: false })
|
||||
stub_feature_flags(harbor_registry_integration: false)
|
||||
stub_feature_flags(ml_experiment_tracking: false)
|
||||
|
|
@ -53,8 +51,8 @@ RSpec.describe 'Project navbar', :with_license, feature_category: :groups_and_pr
|
|||
stub_config(pages: { enabled: true })
|
||||
|
||||
insert_after_sub_nav_item(
|
||||
_('Packages and registries'),
|
||||
within: _('Settings'),
|
||||
_('Releases'),
|
||||
within: _('Deployments'),
|
||||
new_sub_nav_item_name: _('Pages')
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ RSpec.describe 'Pages edits pages settings', :js, feature_category: :pages do
|
|||
before do
|
||||
allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
|
||||
|
||||
stub_feature_flags(show_pages_in_deployments_menu: false)
|
||||
|
||||
project.add_maintainer(user)
|
||||
|
||||
sign_in(user)
|
||||
|
|
@ -82,25 +80,39 @@ RSpec.describe 'Pages edits pages settings', :js, feature_category: :pages do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'project settings page' do
|
||||
it 'renders "Pages" tab' do
|
||||
visit edit_project_path(project)
|
||||
describe 'menu entry' do
|
||||
describe 'on the pages page' do
|
||||
it 'renders "Pages" tab' do
|
||||
visit project_pages_path(project)
|
||||
|
||||
page.within '.nav-sidebar' do
|
||||
expect(page).to have_link('Pages')
|
||||
page.within '.nav-sidebar' do
|
||||
expect(page).to have_link('Pages')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when pages are disabled' do
|
||||
before do
|
||||
allow(Gitlab.config.pages).to receive(:enabled).and_return(false)
|
||||
describe 'in another menu entry under deployments' do
|
||||
context 'when pages are enabled' do
|
||||
it 'renders "Pages" tab' do
|
||||
visit project_environments_path(project)
|
||||
|
||||
page.within '.nav-sidebar' do
|
||||
expect(page).to have_link('Pages')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'does not render "Pages" tab' do
|
||||
visit edit_project_path(project)
|
||||
context 'when pages are disabled' do
|
||||
before do
|
||||
allow(Gitlab.config.pages).to receive(:enabled).and_return(false)
|
||||
end
|
||||
|
||||
page.within '.nav-sidebar' do
|
||||
expect(page).not_to have_link('Pages')
|
||||
it 'does not render "Pages" tab' do
|
||||
visit project_environments_path(project)
|
||||
|
||||
page.within '.nav-sidebar' do
|
||||
expect(page).not_to have_link('Pages')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -65,15 +65,4 @@ RSpec.describe 'User searches project settings', :js, feature_category: :groups_
|
|||
|
||||
it_behaves_like 'can search settings', 'Alerts', 'Error tracking'
|
||||
end
|
||||
|
||||
context 'in Pages page' do
|
||||
before do
|
||||
stub_feature_flags(show_pages_in_deployments_menu: false)
|
||||
allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
|
||||
|
||||
visit project_pages_path(project)
|
||||
end
|
||||
|
||||
it_behaves_like 'can highlight results', 'static website'
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -221,9 +221,11 @@ describe('MembersTable', () => {
|
|||
'col-actions',
|
||||
'gl-display-none!',
|
||||
'gl-lg-display-table-cell!',
|
||||
'gl-vertical-align-middle!',
|
||||
]);
|
||||
expect(findTableCellByMemberId('Actions', members[1].id).classes()).toStrictEqual([
|
||||
'col-actions',
|
||||
'gl-vertical-align-middle!',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Resolvers::DesignManagement::VersionResolver, feature_category: :shared,
|
||||
quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/416627' do
|
||||
RSpec.describe Resolvers::DesignManagement::VersionResolver, feature_category: :shared do
|
||||
include GraphqlHelpers
|
||||
include DesignManagementTestHelpers
|
||||
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ RSpec.describe Gitlab::Database::HealthStatus, feature_category: :database do
|
|||
end
|
||||
|
||||
let(:deferred_worker_health_checker) do
|
||||
Gitlab::SidekiqMiddleware::DeferJobs::DatabaseHealthStatusChecker.new(
|
||||
Gitlab::SidekiqMiddleware::SkipJobs::DatabaseHealthStatusChecker.new(
|
||||
123,
|
||||
deferred_worker.name
|
||||
)
|
||||
|
|
@ -116,7 +116,7 @@ RSpec.describe Gitlab::Database::HealthStatus, feature_category: :database do
|
|||
it 'captures sidekiq job class in the log' do
|
||||
expect(Gitlab::Database::HealthStatus::Logger).to receive(:info).with(
|
||||
status_checker_id: deferred_worker_health_checker.id,
|
||||
status_checker_type: 'Gitlab::SidekiqMiddleware::DeferJobs::DatabaseHealthStatusChecker',
|
||||
status_checker_type: 'Gitlab::SidekiqMiddleware::SkipJobs::DatabaseHealthStatusChecker',
|
||||
job_class_name: deferred_worker_health_checker.job_class_name,
|
||||
health_status_indicator: autovacuum_indicator_class.to_s,
|
||||
indicator_signal: 'Stop',
|
||||
|
|
|
|||
|
|
@ -426,7 +426,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
|
|||
end
|
||||
|
||||
context 'when the job is deferred' do
|
||||
it 'logs start and end of job with deferred job_status' do
|
||||
it 'logs start and end of job with "deferred" job_status' do
|
||||
travel_to(timestamp) do
|
||||
expect(logger).to receive(:info).with(start_payload).ordered
|
||||
expect(logger).to receive(:info).with(deferred_payload).ordered
|
||||
|
|
@ -441,6 +441,21 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the job is dropped' do
|
||||
it 'logs start and end of job with "dropped" job_status' do
|
||||
travel_to(timestamp) do
|
||||
expect(logger).to receive(:info).with(start_payload).ordered
|
||||
expect(logger).to receive(:info).with(dropped_payload).ordered
|
||||
expect(subject).to receive(:log_job_start).and_call_original
|
||||
expect(subject).to receive(:log_job_done).and_call_original
|
||||
|
||||
call_subject(job, 'test_queue') do
|
||||
job['dropped'] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#add_time_keys!' do
|
||||
|
|
|
|||
|
|
@ -1,95 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::SidekiqMiddleware::DeferJobs, feature_category: :scalability do
|
||||
let(:job) { { 'jid' => 123, 'args' => [456] } }
|
||||
let(:queue) { 'test_queue' }
|
||||
let(:test_worker) do
|
||||
Class.new do
|
||||
def self.name
|
||||
'TestWorker'
|
||||
end
|
||||
include ApplicationWorker
|
||||
end
|
||||
end
|
||||
|
||||
subject { described_class.new }
|
||||
|
||||
before do
|
||||
stub_const('TestWorker', test_worker)
|
||||
end
|
||||
|
||||
describe '#call' do
|
||||
context 'with worker not opted for database health check' do
|
||||
context 'when run_sidekiq_jobs feature flag is disabled' do
|
||||
let(:deferred_jobs_metric) { instance_double(Prometheus::Client::Counter, increment: true) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(run_sidekiq_jobs_TestWorker: false)
|
||||
allow(Gitlab::Metrics).to receive(:counter).and_call_original
|
||||
allow(Gitlab::Metrics).to receive(:counter).with(described_class::DEFERRED_COUNTER, anything)
|
||||
.and_return(deferred_jobs_metric)
|
||||
end
|
||||
|
||||
it 'defers the job' do
|
||||
expect(TestWorker).to receive(:perform_in).with(described_class::DELAY, *job['args'])
|
||||
expect { |b| subject.call(TestWorker.new, job, queue, &b) }.not_to yield_control
|
||||
end
|
||||
|
||||
it 'increments the defer_count' do
|
||||
(1..5).each do |count|
|
||||
subject.call(TestWorker.new, job, queue)
|
||||
expect(job).to include('deferred_count' => count)
|
||||
end
|
||||
end
|
||||
|
||||
it 'increments the counter' do
|
||||
expect(deferred_jobs_metric).to receive(:increment).with({ worker: "TestWorker" })
|
||||
|
||||
subject.call(TestWorker.new, job, queue)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when run_sidekiq_jobs feature flag is enabled' do
|
||||
it 'runs the job normally' do
|
||||
expect { |b| subject.call(TestWorker.new, job, queue, &b) }.to yield_control
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with worker opted for database health check' do
|
||||
let(:health_signal_attrs) { { gitlab_schema: :gitlab_main, delay: 1.minute, tables: [:users] } }
|
||||
|
||||
around do |example|
|
||||
with_sidekiq_server_middleware do |chain|
|
||||
chain.add described_class
|
||||
Sidekiq::Testing.inline! { example.run }
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
TestWorker.defer_on_database_health_signal(*health_signal_attrs.values)
|
||||
end
|
||||
|
||||
context 'without any stop signal from database health check' do
|
||||
it 'runs the job normally' do
|
||||
expect { |b| subject.call(TestWorker.new, job, queue, &b) }.to yield_control
|
||||
end
|
||||
end
|
||||
|
||||
context 'with stop signal from database health check' do
|
||||
before do
|
||||
stop_signal = instance_double("Gitlab::Database::HealthStatus::Signals::Stop", stop?: true)
|
||||
allow(Gitlab::Database::HealthStatus).to receive(:evaluate).and_return([stop_signal])
|
||||
end
|
||||
|
||||
it 'defers the job by set time' do
|
||||
expect(TestWorker).to receive(:perform_in).with(health_signal_attrs[:delay], *job['args'])
|
||||
|
||||
TestWorker.perform_async(*job['args'])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -400,7 +400,7 @@ RSpec.describe Gitlab::SidekiqMiddleware::ServerMetrics do
|
|||
Gitlab::SidekiqMiddleware.server_configurator(
|
||||
metrics: true,
|
||||
arguments_logger: false,
|
||||
defer_jobs: false
|
||||
skip_jobs: false
|
||||
).call(chain)
|
||||
|
||||
Sidekiq::Testing.inline! { example.run }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,151 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::SidekiqMiddleware::SkipJobs, feature_category: :scalability do
|
||||
let(:job) { { 'jid' => 123, 'args' => [456] } }
|
||||
let(:queue) { 'test_queue' }
|
||||
let(:worker) do
|
||||
Class.new do
|
||||
def self.name
|
||||
'TestWorker'
|
||||
end
|
||||
include ApplicationWorker
|
||||
end
|
||||
end
|
||||
|
||||
subject { described_class.new }
|
||||
|
||||
before do
|
||||
stub_const('TestWorker', worker)
|
||||
stub_feature_flags("drop_sidekiq_jobs_#{TestWorker.name}": false)
|
||||
end
|
||||
|
||||
describe '#call' do
|
||||
context 'with worker not opted for database health check' do
|
||||
describe "with all combinations of drop and defer FFs" do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
let(:metric) { instance_double(Prometheus::Client::Counter, increment: true) }
|
||||
|
||||
shared_examples 'runs the job normally' do
|
||||
it 'yields control' do
|
||||
expect { |b| subject.call(TestWorker.new, job, queue, &b) }.to yield_control
|
||||
end
|
||||
|
||||
it 'does not increment any metric counter' do
|
||||
expect(metric).not_to receive(:increment)
|
||||
|
||||
subject.call(TestWorker.new, job, queue) { nil }
|
||||
end
|
||||
|
||||
it 'does not increment deferred_count' do
|
||||
subject.call(TestWorker.new, job, queue) { nil }
|
||||
|
||||
expect(job).not_to include('deferred_count')
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'drops the job' do
|
||||
it 'does not yield control' do
|
||||
expect { |b| subject.call(TestWorker.new, job, queue, &b) }.not_to yield_control
|
||||
end
|
||||
|
||||
it 'increments counter' do
|
||||
expect(metric).to receive(:increment).with({ worker: "TestWorker", action: "dropped" })
|
||||
|
||||
subject.call(TestWorker.new, job, queue) { nil }
|
||||
end
|
||||
|
||||
it 'does not increment deferred_count' do
|
||||
subject.call(TestWorker.new, job, queue) { nil }
|
||||
|
||||
expect(job).not_to include('deferred_count')
|
||||
end
|
||||
|
||||
it 'has dropped field in job equal to true' do
|
||||
subject.call(TestWorker.new, job, queue) { nil }
|
||||
|
||||
expect(job).to include({ 'dropped' => true })
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'defers the job' do
|
||||
it 'does not yield control' do
|
||||
expect { |b| subject.call(TestWorker.new, job, queue, &b) }.not_to yield_control
|
||||
end
|
||||
|
||||
it 'delays the job' do
|
||||
expect(TestWorker).to receive(:perform_in).with(described_class::DELAY, *job['args'])
|
||||
|
||||
subject.call(TestWorker.new, job, queue) { nil }
|
||||
end
|
||||
|
||||
it 'increments counter' do
|
||||
expect(metric).to receive(:increment).with({ worker: "TestWorker", action: "deferred" })
|
||||
|
||||
subject.call(TestWorker.new, job, queue) { nil }
|
||||
end
|
||||
|
||||
it 'has deferred related fields in job payload' do
|
||||
subject.call(TestWorker.new, job, queue) { nil }
|
||||
|
||||
expect(job).to include({ 'deferred' => true, 'deferred_by' => :feature_flag, 'deferred_count' => 1 })
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
stub_feature_flags("drop_sidekiq_jobs_#{TestWorker.name}": drop_ff)
|
||||
stub_feature_flags("run_sidekiq_jobs_#{TestWorker.name}": run_ff)
|
||||
allow(Gitlab::Metrics).to receive(:counter).and_call_original
|
||||
allow(Gitlab::Metrics).to receive(:counter).with(described_class::COUNTER, anything).and_return(metric)
|
||||
end
|
||||
|
||||
where(:drop_ff, :run_ff, :resulting_behavior) do
|
||||
false | true | "runs the job normally"
|
||||
true | true | "drops the job"
|
||||
false | false | "defers the job"
|
||||
true | false | "drops the job"
|
||||
end
|
||||
|
||||
with_them do
|
||||
it_behaves_like params[:resulting_behavior]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with worker opted for database health check' do
|
||||
let(:health_signal_attrs) { { gitlab_schema: :gitlab_main, delay: 1.minute, tables: [:users] } }
|
||||
|
||||
around do |example|
|
||||
with_sidekiq_server_middleware do |chain|
|
||||
chain.add described_class
|
||||
Sidekiq::Testing.inline! { example.run }
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
TestWorker.defer_on_database_health_signal(*health_signal_attrs.values)
|
||||
end
|
||||
|
||||
context 'without any stop signal from database health check' do
|
||||
it 'runs the job normally' do
|
||||
expect { |b| subject.call(TestWorker.new, job, queue, &b) }.to yield_control
|
||||
end
|
||||
end
|
||||
|
||||
context 'with stop signal from database health check' do
|
||||
before do
|
||||
stop_signal = instance_double("Gitlab::Database::HealthStatus::Signals::Stop", stop?: true)
|
||||
allow(Gitlab::Database::HealthStatus).to receive(:evaluate).and_return([stop_signal])
|
||||
end
|
||||
|
||||
it 'defers the job by set time' do
|
||||
expect(TestWorker).to receive(:perform_in).with(health_signal_attrs[:delay], *job['args'])
|
||||
|
||||
TestWorker.perform_async(*job['args'])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -31,6 +31,7 @@ RSpec.describe Gitlab::SidekiqMiddleware do
|
|||
shared_examples "a middleware chain" do
|
||||
before do
|
||||
configurator.call(chain)
|
||||
stub_feature_flags("drop_sidekiq_jobs_#{worker_class.name}": false) # not dropping the job
|
||||
end
|
||||
it "passes through the right middlewares", :aggregate_failures do
|
||||
enabled_sidekiq_middlewares.each do |middleware|
|
||||
|
|
@ -69,7 +70,7 @@ RSpec.describe Gitlab::SidekiqMiddleware do
|
|||
::Gitlab::SidekiqMiddleware::WorkerContext::Server,
|
||||
::Gitlab::SidekiqMiddleware::DuplicateJobs::Server,
|
||||
::Gitlab::Database::LoadBalancing::SidekiqServerMiddleware,
|
||||
::Gitlab::SidekiqMiddleware::DeferJobs
|
||||
::Gitlab::SidekiqMiddleware::SkipJobs
|
||||
]
|
||||
end
|
||||
|
||||
|
|
@ -79,9 +80,7 @@ RSpec.describe Gitlab::SidekiqMiddleware do
|
|||
described_class.server_configurator(
|
||||
metrics: true,
|
||||
arguments_logger: true,
|
||||
# defer_jobs has to be false because this middleware defers jobs from a worker based on
|
||||
# `worker` type feature flag which is enabled by default in test
|
||||
defer_jobs: false
|
||||
skip_jobs: false
|
||||
).call(chain)
|
||||
|
||||
Sidekiq::Testing.inline! { example.run }
|
||||
|
|
@ -114,7 +113,7 @@ RSpec.describe Gitlab::SidekiqMiddleware do
|
|||
described_class.server_configurator(
|
||||
metrics: false,
|
||||
arguments_logger: false,
|
||||
defer_jobs: false
|
||||
skip_jobs: false
|
||||
)
|
||||
end
|
||||
|
||||
|
|
@ -122,7 +121,7 @@ RSpec.describe Gitlab::SidekiqMiddleware do
|
|||
[
|
||||
Gitlab::SidekiqMiddleware::ServerMetrics,
|
||||
Gitlab::SidekiqMiddleware::ArgumentsLogger,
|
||||
Gitlab::SidekiqMiddleware::DeferJobs
|
||||
Gitlab::SidekiqMiddleware::SkipJobs
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -68,5 +68,31 @@ RSpec.describe Sidebars::Projects::Menus::DeploymentsMenu, feature_category: :na
|
|||
|
||||
it_behaves_like 'access rights checks'
|
||||
end
|
||||
|
||||
describe 'Pages' do
|
||||
let(:item_id) { :pages }
|
||||
|
||||
before do
|
||||
allow(project).to receive(:pages_available?).and_return(pages_enabled)
|
||||
end
|
||||
|
||||
describe 'when pages are enabled' do
|
||||
let(:pages_enabled) { true }
|
||||
|
||||
it { is_expected.not_to be_nil }
|
||||
|
||||
describe 'when the user does not have access' do
|
||||
let(:user) { nil }
|
||||
|
||||
it { is_expected.to be_nil }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when pages are not enabled' do
|
||||
let(:pages_enabled) { false }
|
||||
|
||||
it { is_expected.to be_nil }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,10 +10,6 @@ RSpec.describe Sidebars::Projects::Menus::SettingsMenu, feature_category: :navig
|
|||
|
||||
subject { described_class.new(context) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(show_pages_in_deployments_menu: false)
|
||||
end
|
||||
|
||||
describe '#render?' do
|
||||
it 'returns false when menu does not have any menu items' do
|
||||
allow(subject).to receive(:has_renderable_items?).and_return(false)
|
||||
|
|
@ -117,32 +113,6 @@ RSpec.describe Sidebars::Projects::Menus::SettingsMenu, feature_category: :navig
|
|||
end
|
||||
end
|
||||
|
||||
describe 'Pages' do
|
||||
let(:item_id) { :pages }
|
||||
|
||||
before do
|
||||
allow(project).to receive(:pages_available?).and_return(pages_enabled)
|
||||
end
|
||||
|
||||
describe 'when pages are enabled' do
|
||||
let(:pages_enabled) { true }
|
||||
|
||||
specify { is_expected.not_to be_nil }
|
||||
|
||||
describe 'when the user does not have access' do
|
||||
let(:user) { nil }
|
||||
|
||||
specify { is_expected.to be_nil }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when pages are not enabled' do
|
||||
let(:pages_enabled) { false }
|
||||
|
||||
specify { is_expected.to be_nil }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Merge requests' do
|
||||
let(:item_id) { :merge_requests }
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching, feature_categ
|
|||
|
||||
it { is_expected.to be_kind_of(ReactiveCaching) }
|
||||
it { is_expected.to nullify_if_blank(:external_url) }
|
||||
it { is_expected.to nullify_if_blank(:kubernetes_namespace) }
|
||||
|
||||
it { is_expected.to belong_to(:project).required }
|
||||
it { is_expected.to belong_to(:merge_request).optional }
|
||||
|
|
@ -36,6 +37,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching, feature_categ
|
|||
it { is_expected.to validate_length_of(:slug).is_at_most(24) }
|
||||
|
||||
it { is_expected.to validate_length_of(:external_url).is_at_most(255) }
|
||||
it { is_expected.to validate_length_of(:kubernetes_namespace).is_at_most(63) }
|
||||
|
||||
describe 'validation' do
|
||||
it 'does not become invalid record when external_url is empty' do
|
||||
|
|
|
|||
|
|
@ -134,7 +134,8 @@ RSpec.describe API::Internal::Kubernetes, feature_category: :deployment_manageme
|
|||
k8s_api_proxy_requests_unique_users_via_ci_access: [10, 999, 777, 10],
|
||||
k8s_api_proxy_requests_unique_agents_via_ci_access: [10, 999, 777, 10],
|
||||
k8s_api_proxy_requests_unique_users_via_user_access: [10, 999, 777, 10],
|
||||
k8s_api_proxy_requests_unique_agents_via_user_access: [10, 999, 777, 10]
|
||||
k8s_api_proxy_requests_unique_agents_via_user_access: [10, 999, 777, 10],
|
||||
flux_git_push_notified_unique_projects: [10, 999, 777, 10]
|
||||
}
|
||||
expected_counters = {
|
||||
kubernetes_agent_gitops_sync: request_count * counters[:gitops_sync],
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ RSpec.describe Environments::CreateService, feature_category: :environment_manag
|
|||
describe '#execute' do
|
||||
subject { service.execute }
|
||||
|
||||
let(:params) { { name: 'production', external_url: 'https://gitlab.com', tier: :production } }
|
||||
let(:params) { { name: 'production', external_url: 'https://gitlab.com', tier: :production, kubernetes_namespace: 'default' } }
|
||||
|
||||
it 'creates an environment' do
|
||||
expect { subject }.to change { ::Environment.count }.by(1)
|
||||
|
|
@ -27,6 +27,7 @@ RSpec.describe Environments::CreateService, feature_category: :environment_manag
|
|||
expect(response.payload[:environment].name).to eq('production')
|
||||
expect(response.payload[:environment].external_url).to eq('https://gitlab.com')
|
||||
expect(response.payload[:environment].tier).to eq('production')
|
||||
expect(response.payload[:environment].kubernetes_namespace).to eq('default')
|
||||
end
|
||||
|
||||
context 'with a cluster agent' do
|
||||
|
|
|
|||
|
|
@ -28,6 +28,21 @@ RSpec.describe Environments::UpdateService, feature_category: :environment_manag
|
|||
expect(response.payload[:environment]).to eq(environment)
|
||||
end
|
||||
|
||||
context 'when setting a kubernetes namespace to the environment' do
|
||||
let(:params) { { kubernetes_namespace: 'default' } }
|
||||
|
||||
it 'updates the kubernetes namespace' do
|
||||
expect { subject }.to change { environment.reload.kubernetes_namespace }.to('default')
|
||||
end
|
||||
|
||||
it 'returns successful response' do
|
||||
response = subject
|
||||
|
||||
expect(response).to be_success
|
||||
expect(response.payload[:environment]).to eq(environment)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when setting a cluster agent to the environment' do
|
||||
let_it_be(:agent_management_project) { create(:project) }
|
||||
let_it_be(:cluster_agent) { create(:cluster_agent, project: agent_management_project) }
|
||||
|
|
|
|||
|
|
@ -436,7 +436,7 @@ RSpec.configure do |config|
|
|||
Gitlab::SidekiqMiddleware.server_configurator(
|
||||
metrics: false, # The metrics don't go anywhere in tests
|
||||
arguments_logger: false, # We're not logging the regular messages for inline jobs
|
||||
defer_jobs: false # We're not deferring jobs for inline tests
|
||||
skip_jobs: false # We're not skipping jobs for inline tests
|
||||
).call(chain)
|
||||
chain.add DisableQueryLimit
|
||||
chain.insert_after ::Gitlab::SidekiqMiddleware::RequestStoreMiddleware, IsolatedRequestStore
|
||||
|
|
|
|||
|
|
@ -74,6 +74,13 @@ RSpec.shared_context 'structured_logger' do
|
|||
)
|
||||
end
|
||||
|
||||
let(:dropped_payload) do
|
||||
end_payload.merge(
|
||||
'message' => 'TestWorker JID-da883554ee4fe414012f5f42: dropped: 0.0 sec',
|
||||
'job_status' => 'dropped'
|
||||
)
|
||||
end
|
||||
|
||||
let(:exception_payload) do
|
||||
end_payload.merge(
|
||||
'message' => 'TestWorker JID-da883554ee4fe414012f5f42: fail: 0.0 sec',
|
||||
|
|
|
|||
|
|
@ -105,26 +105,10 @@ RSpec.describe 'projects/edit' do
|
|||
end
|
||||
|
||||
describe 'pages menu entry callout' do
|
||||
context 'with feature flag disabled' do
|
||||
before do
|
||||
stub_feature_flags(show_pages_in_deployments_menu: false)
|
||||
end
|
||||
it 'does show a callout' do
|
||||
render
|
||||
|
||||
it 'does not show a callout' do
|
||||
render
|
||||
expect(rendered).not_to have_content('GitLab Pages has moved')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with feature flag enabled' do
|
||||
before do
|
||||
stub_feature_flags(show_pages_in_deployments_menu: true)
|
||||
end
|
||||
|
||||
it 'does show a callout' do
|
||||
render
|
||||
expect(rendered).to have_content('GitLab Pages has moved')
|
||||
end
|
||||
expect(rendered).to have_content(_('GitLab Pages has moved'))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue