Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
0847321aee
commit
7424d727b8
|
|
@ -119,6 +119,9 @@ workflow:
|
|||
variables:
|
||||
<<: *default-ruby-variables
|
||||
PIPELINE_NAME: 'Ruby $RUBY_VERSION $CI_COMMIT_BRANCH branch pipeline'
|
||||
- if: '$CI_PROJECT_PATH == "gitlab/gitaly" && $CI_PIPELINE_SOURCE == "parent_pipeline" && $GITALY_TEST'
|
||||
variables:
|
||||
PIPELINE_NAME: 'Gitaly Rails Test Pipeline'
|
||||
|
||||
variables:
|
||||
PG_VERSION: "14"
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ AllCops:
|
|||
TargetRubyVersion: <%= RUBY_VERSION[/^\d+\.\d+/, 0] %>
|
||||
TargetRailsVersion: 6.0
|
||||
Exclude:
|
||||
- 'gems/**/*'
|
||||
- 'vendor/**/*'
|
||||
- 'node_modules/**/*'
|
||||
- 'db/fixtures/**/*'
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ const messageHtml = `
|
|||
<li>${s__("AdminUsers|The user can't log in.")}</li>
|
||||
<li>${s__("AdminUsers|The user can't access git repositories.")}</li>
|
||||
<li>${s__(
|
||||
'AdminUsers|Issues and merge requests authored by this user are hidden from other users.',
|
||||
'AdminUsers|Projects, issues, merge requests, and comments of this user are hidden from other users.',
|
||||
)}</li>
|
||||
</ul>
|
||||
<p>${s__('AdminUsers|You can unban their account in the future. Their data remains intact.')}</p>
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@ export const DORA_METRICS = {
|
|||
};
|
||||
|
||||
const VSA_FLOW_METRICS_GROUP = {
|
||||
key: 'key_metrics',
|
||||
title: s__('ValueStreamAnalytics|Key metrics'),
|
||||
key: 'lifecycle_metrics',
|
||||
title: s__('ValueStreamAnalytics|Lifecycle metrics'),
|
||||
keys: Object.values(FLOW_METRICS),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
<script>
|
||||
import { GlDropdownItem, GlAvatarLabeled, GlLoadingIcon } from '@gitlab/ui';
|
||||
import { GlAvatarLabeled, GlLoadingIcon } from '@gitlab/ui';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlDropdownItem,
|
||||
GlAvatarLabeled,
|
||||
GlLoadingIcon,
|
||||
},
|
||||
|
|
@ -43,7 +42,7 @@ export default {
|
|||
|
||||
data() {
|
||||
return {
|
||||
selectedIndex: 0,
|
||||
selectedIndex: -1,
|
||||
};
|
||||
},
|
||||
|
||||
|
|
@ -95,7 +94,7 @@ export default {
|
|||
|
||||
watch: {
|
||||
items() {
|
||||
this.selectedIndex = 0;
|
||||
this.selectedIndex = -1;
|
||||
},
|
||||
selectedIndex() {
|
||||
this.scrollIntoView();
|
||||
|
|
@ -193,7 +192,7 @@ export default {
|
|||
},
|
||||
|
||||
scrollIntoView() {
|
||||
this.$refs.dropdownItems[this.selectedIndex].$el.scrollIntoView({ block: 'nearest' });
|
||||
this.$refs.dropdownItems[this.selectedIndex]?.scrollIntoView({ block: 'nearest' });
|
||||
},
|
||||
|
||||
selectItem(index) {
|
||||
|
|
@ -215,73 +214,85 @@ export default {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<ul
|
||||
v-if="!loading"
|
||||
:class="{ show: items.length > 0 }"
|
||||
class="gl-dropdown dropdown-menu gl-relative gl-m-0!"
|
||||
data-testid="content-editor-suggestions-dropdown"
|
||||
>
|
||||
<div class="gl-dropdown-inner gl-overflow-y-auto">
|
||||
<gl-dropdown-item
|
||||
v-for="(item, index) in items"
|
||||
ref="dropdownItems"
|
||||
:key="index"
|
||||
:class="{ 'gl-bg-gray-50': index === selectedIndex }"
|
||||
@click="selectItem(index)"
|
||||
<div class="gl-new-dropdown content-editor-suggestions-dropdown">
|
||||
<div class="gl-new-dropdown-panel gl-display-block! gl-absolute">
|
||||
<div class="gl-new-dropdown-inner">
|
||||
<ul
|
||||
v-if="!loading && items.length > 0"
|
||||
class="gl-new-dropdown-contents"
|
||||
data-testid="content-editor-suggestions-dropdown"
|
||||
>
|
||||
<gl-avatar-labeled
|
||||
v-if="isUser"
|
||||
:label="item.username"
|
||||
:sub-label="avatarSubLabel(item)"
|
||||
:src="item.avatar_url"
|
||||
:entity-name="item.username"
|
||||
:shape="item.type === 'Group' ? 'rect' : 'circle'"
|
||||
:size="32"
|
||||
/>
|
||||
<span v-if="isIssue || isMergeRequest">
|
||||
<small>{{ item.iid }}</small>
|
||||
{{ item.title }}
|
||||
</span>
|
||||
<span v-if="isVulnerability || isSnippet">
|
||||
<small>{{ item.id }}</small>
|
||||
{{ item.title }}
|
||||
</span>
|
||||
<span v-if="isEpic">
|
||||
<small>{{ item.reference }}</small>
|
||||
{{ item.title }}
|
||||
</span>
|
||||
<span v-if="isMilestone">
|
||||
{{ item.title }}
|
||||
</span>
|
||||
<span v-if="isLabel" class="gl-display-flex gl-align-items-center">
|
||||
<span
|
||||
data-testid="label-color-box"
|
||||
class="gl-rounded-base gl-display-block gl-w-5 gl-h-5 gl-mr-3"
|
||||
:style="{ backgroundColor: item.color }"
|
||||
></span>
|
||||
{{ item.title }}
|
||||
</span>
|
||||
<span v-if="isCommand">
|
||||
/{{ item.name }} <small> {{ item.params[0] }} </small><br />
|
||||
<em>
|
||||
<small> {{ item.description }} </small>
|
||||
</em>
|
||||
</span>
|
||||
<div v-if="isEmoji" class="gl-display-flex gl-align-items-center">
|
||||
<div class="gl-pr-4 gl-font-lg">{{ item.e }}</div>
|
||||
<div class="gl-flex-grow-1">
|
||||
{{ item.name }}<br />
|
||||
<small>{{ item.d }}</small>
|
||||
<li
|
||||
v-for="(item, index) in items"
|
||||
:key="index"
|
||||
role="presentation"
|
||||
class="gl-new-dropdown-item"
|
||||
:class="{ focused: index === selectedIndex }"
|
||||
>
|
||||
<div
|
||||
ref="dropdownItems"
|
||||
type="button"
|
||||
role="menuitem"
|
||||
class="gl-new-dropdown-item-content"
|
||||
@click="selectItem(index)"
|
||||
>
|
||||
<div class="gl-new-dropdown-item-text-wrapper">
|
||||
<gl-avatar-labeled
|
||||
v-if="isUser"
|
||||
:label="item.username"
|
||||
:sub-label="avatarSubLabel(item)"
|
||||
:src="item.avatar_url"
|
||||
:entity-name="item.username"
|
||||
:shape="item.type === 'Group' ? 'rect' : 'circle'"
|
||||
:size="32"
|
||||
/>
|
||||
<span v-if="isIssue || isMergeRequest">
|
||||
<small>{{ item.iid }}</small>
|
||||
{{ item.title }}
|
||||
</span>
|
||||
<span v-if="isVulnerability || isSnippet">
|
||||
<small>{{ item.id }}</small>
|
||||
{{ item.title }}
|
||||
</span>
|
||||
<span v-if="isEpic">
|
||||
<small>{{ item.reference }}</small>
|
||||
{{ item.title }}
|
||||
</span>
|
||||
<span v-if="isMilestone">
|
||||
{{ item.title }}
|
||||
</span>
|
||||
<span v-if="isLabel" class="gl-display-flex">
|
||||
<span
|
||||
data-testid="label-color-box"
|
||||
class="dropdown-label-box gl-flex-shrink-0 gl-top-0 gl-mr-3"
|
||||
:style="{ backgroundColor: item.color }"
|
||||
></span>
|
||||
{{ item.title }}
|
||||
</span>
|
||||
<div v-if="isCommand">
|
||||
<div class="gl-mb-1">
|
||||
<span class="gl-font-weight-bold">/{{ item.name }}</span>
|
||||
<em class="gl-text-gray-500 gl-font-sm">{{ item.params[0] }}</em>
|
||||
</div>
|
||||
<small class="gl-text-gray-500"> {{ item.description }} </small>
|
||||
</div>
|
||||
<div v-if="isEmoji" class="gl-display-flex gl-align-items-center">
|
||||
<div class="gl-pr-4 gl-font-lg">{{ item.e }}</div>
|
||||
<div class="gl-flex-grow-1">
|
||||
{{ item.name }}<br />
|
||||
<small>{{ item.d }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<div v-if="loading" class="gl-new-dropdown show dropdown-menu gl-relative gl-m-0!">
|
||||
<div class="gl-new-dropdown-inner gl-overflow-y-auto">
|
||||
<div class="gl-px-5">
|
||||
<gl-loading-icon size="sm" class="gl-display-inline-block" /> {{ __('Loading...') }}
|
||||
</div>
|
||||
</div>
|
||||
</gl-dropdown-item>
|
||||
</div>
|
||||
</ul>
|
||||
<div v-if="loading" class="gl-dropdown show dropdown-menu gl-relative gl-m-0!">
|
||||
<div class="gl-dropdown-inner gl-overflow-y-auto">
|
||||
<div class="gl-px-5">
|
||||
<gl-loading-icon size="sm" class="gl-display-inline-block" /> {{ __('Loading...') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import importGroupIllustration from '@gitlab/svgs/dist/illustrations/group-import.svg?raw';
|
||||
import newGroupIllustration from '@gitlab/svgs/dist/illustrations/group-new.svg?raw';
|
||||
import GROUP_IMPORT_SVG_URL from '@gitlab/svgs/dist/illustrations/group-import.svg?url';
|
||||
import GROUP_NEW_SVG_URL from '@gitlab/svgs/dist/illustrations/group-new.svg?url';
|
||||
|
||||
import { s__ } from '~/locale';
|
||||
import NewNamespacePage from '~/vue_shared/new_namespace/new_namespace_page.vue';
|
||||
|
|
@ -69,12 +69,12 @@ export default {
|
|||
description: s__(
|
||||
'GroupsNew|Assemble related projects together and grant members access to several projects at once.',
|
||||
),
|
||||
illustration: newGroupIllustration,
|
||||
details: createGroupDescriptionDetails,
|
||||
detailProps: {
|
||||
parentGroupName: this.parentGroupName,
|
||||
importExistingGroupPath: this.importExistingGroupPath,
|
||||
},
|
||||
imageSrc: GROUP_NEW_SVG_URL,
|
||||
},
|
||||
{
|
||||
name: 'import-group-pane',
|
||||
|
|
@ -83,8 +83,8 @@ export default {
|
|||
description: s__(
|
||||
'GroupsNew|Import a group and related data from another GitLab instance.',
|
||||
),
|
||||
illustration: importGroupIllustration,
|
||||
details: 'Migrate your existing groups from another instance of GitLab.',
|
||||
imageSrc: GROUP_IMPORT_SVG_URL,
|
||||
},
|
||||
];
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<script>
|
||||
import createFromTemplateIllustration from '@gitlab/svgs/dist/illustrations/project-create-from-template-sm.svg?raw';
|
||||
import blankProjectIllustration from '@gitlab/svgs/dist/illustrations/project-create-new-sm.svg?raw';
|
||||
import importProjectIllustration from '@gitlab/svgs/dist/illustrations/project-import-sm.svg?raw';
|
||||
import ciCdProjectIllustration from '@gitlab/svgs/dist/illustrations/project-run-CICD-pipelines-sm.svg?raw';
|
||||
import PROJECT_CREATE_FROM_TEMPLATE_SVG_URL from '@gitlab/svgs/dist/illustrations/project-create-from-template-sm.svg?url';
|
||||
import PROJECT_CREATE_NEW_SVG_URL from '@gitlab/svgs/dist/illustrations/project-create-new-sm.svg?url';
|
||||
import PROJECT_IMPORT_SVG_URL from '@gitlab/svgs/dist/illustrations/project-import-sm.svg?url';
|
||||
import PROJECT_RUN_CICD_PIPELINES_SVG_URL from '@gitlab/svgs/dist/illustrations/project-run-CICD-pipelines-sm.svg?url';
|
||||
import SafeHtml from '~/vue_shared/directives/safe_html';
|
||||
import { s__ } from '~/locale';
|
||||
import NewNamespacePage from '~/vue_shared/new_namespace/new_namespace_page.vue';
|
||||
|
|
@ -19,7 +19,7 @@ const PANELS = [
|
|||
description: s__(
|
||||
'ProjectsNew|Create a blank project to store your files, plan your work, and collaborate on code, among other things.',
|
||||
),
|
||||
illustration: blankProjectIllustration,
|
||||
imageSrc: PROJECT_CREATE_NEW_SVG_URL,
|
||||
},
|
||||
{
|
||||
key: 'template',
|
||||
|
|
@ -29,7 +29,7 @@ const PANELS = [
|
|||
description: s__(
|
||||
'ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly.',
|
||||
),
|
||||
illustration: createFromTemplateIllustration,
|
||||
imageSrc: PROJECT_CREATE_FROM_TEMPLATE_SVG_URL,
|
||||
},
|
||||
{
|
||||
key: 'import',
|
||||
|
|
@ -39,7 +39,7 @@ const PANELS = [
|
|||
description: s__(
|
||||
'ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab.',
|
||||
),
|
||||
illustration: importProjectIllustration,
|
||||
imageSrc: PROJECT_IMPORT_SVG_URL,
|
||||
},
|
||||
{
|
||||
key: 'ci',
|
||||
|
|
@ -47,7 +47,7 @@ const PANELS = [
|
|||
selector: '#ci-cd-project-pane',
|
||||
title: s__('ProjectsNew|Run CI/CD for external repository'),
|
||||
description: s__('ProjectsNew|Connect your external repository to GitLab CI/CD.'),
|
||||
illustration: ciCdProjectIllustration,
|
||||
imageSrc: PROJECT_RUN_CICD_PIPELINES_SVG_URL,
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
<script>
|
||||
import SafeHtml from '~/vue_shared/directives/safe_html';
|
||||
import Tracking from '~/tracking';
|
||||
|
||||
export default {
|
||||
directives: {
|
||||
SafeHtml,
|
||||
},
|
||||
mixins: [Tracking.mixin()],
|
||||
props: {
|
||||
title: {
|
||||
|
|
@ -38,9 +34,10 @@ export default {
|
|||
@click="track('click_tab', { label: panel.name })"
|
||||
>
|
||||
<div
|
||||
v-safe-html="panel.illustration"
|
||||
class="new-namespace-panel-illustration gl-text-white gl-display-flex gl-flex-shrink-0 gl-justify-content-center"
|
||||
></div>
|
||||
class="new-namespace-panel-illustration gl-display-flex gl-flex-shrink-0 gl-justify-content-center"
|
||||
>
|
||||
<img aria-hidden :src="panel.imageSrc" />
|
||||
</div>
|
||||
<div class="gl-pl-4">
|
||||
<h3 class="gl-font-size-h2 gl-reset-color">
|
||||
{{ panel.title }}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
<script>
|
||||
import { GlBreadcrumb, GlIcon } from '@gitlab/ui';
|
||||
import SafeHtml from '~/vue_shared/directives/safe_html';
|
||||
import NewTopLevelGroupAlert from '~/groups/components/new_top_level_group_alert.vue';
|
||||
|
||||
import SuperSidebarToggle from '~/super_sidebar/components/super_sidebar_toggle.vue';
|
||||
|
|
@ -18,9 +17,6 @@ export default {
|
|||
LegacyContainer,
|
||||
SuperSidebarToggle,
|
||||
},
|
||||
directives: {
|
||||
SafeHtml,
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
|
|
@ -137,7 +133,9 @@ export default {
|
|||
|
||||
<template v-if="activePanel">
|
||||
<div class="gl-display-flex gl-align-items-center gl-py-5">
|
||||
<div v-safe-html="activePanel.illustration" class="gl-text-white col-auto"></div>
|
||||
<div class="col-auto">
|
||||
<img aria-hidden :src="activePanel.imageSrc" />
|
||||
</div>
|
||||
<div class="col">
|
||||
<h4>{{ activePanel.title }}</h4>
|
||||
|
||||
|
|
|
|||
|
|
@ -179,6 +179,17 @@
|
|||
min-width: auto;
|
||||
}
|
||||
|
||||
.content-editor-suggestions-dropdown {
|
||||
.gl-new-dropdown-panel {
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
li.focused div.gl-new-dropdown-item-content {
|
||||
@include gl-focus($inset: true);
|
||||
@include gl-bg-gray-50;
|
||||
}
|
||||
}
|
||||
|
||||
.bubble-menu-form {
|
||||
min-width: 320px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ class Profiles::NotificationsController < Profiles::ApplicationController
|
|||
projects = project_notifications.map(&:source)
|
||||
ActiveRecord::Associations::Preloader.new(
|
||||
records: projects,
|
||||
associations: { namespace: [:route, :owner], group: [] }
|
||||
associations: { namespace: [:route, :owner], group: [], creator: [] }
|
||||
).call
|
||||
Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects, current_user).execute
|
||||
|
||||
|
|
|
|||
|
|
@ -53,6 +53,10 @@ class ProjectsFinder < UnionFinder
|
|||
init_collection
|
||||
end
|
||||
|
||||
if Feature.enabled?(:hide_projects_of_banned_users)
|
||||
collection = without_created_and_owned_by_banned_user(collection)
|
||||
end
|
||||
|
||||
use_cte = params.delete(:use_cte)
|
||||
collection = Project.wrap_with_cte(collection) if use_cte
|
||||
collection = filter_projects(collection)
|
||||
|
|
@ -282,6 +286,12 @@ class ProjectsFinder < UnionFinder
|
|||
|
||||
{ min_access_level: params[:min_access_level] }
|
||||
end
|
||||
|
||||
def without_created_and_owned_by_banned_user(projects)
|
||||
return projects if current_user&.can?(:admin_all_resources)
|
||||
|
||||
projects.without_created_and_owned_by_banned_user
|
||||
end
|
||||
end
|
||||
|
||||
ProjectsFinder.prepend_mod_with('ProjectsFinder')
|
||||
|
|
|
|||
|
|
@ -79,7 +79,6 @@ module EnvironmentHelper
|
|||
can_destroy_environment: can_destroy_environment?(environment),
|
||||
can_stop_environment: can?(current_user, :stop_environment, environment),
|
||||
can_admin_environment: can?(current_user, :admin_environment, project),
|
||||
**environment_metrics_path(project, environment),
|
||||
environments_fetch_path: project_environments_path(project, format: :json),
|
||||
environment_edit_path: edit_project_environment_path(project, environment),
|
||||
environment_stop_path: stop_project_environment_path(project, environment),
|
||||
|
|
@ -96,10 +95,4 @@ module EnvironmentHelper
|
|||
def environments_detail_data_json(user, project, environment)
|
||||
environments_detail_data(user, project, environment).to_json
|
||||
end
|
||||
|
||||
def environment_metrics_path(project, environment)
|
||||
return {} if Feature.enabled?(:remove_monitor_metrics)
|
||||
|
||||
{ environment_metrics_path: project_metrics_dashboard_path(project, environment: environment) }
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ module EnvironmentsHelper
|
|||
|
||||
metrics_data = {}
|
||||
metrics_data.merge!(project_metrics_data(project)) if project
|
||||
metrics_data.merge!(environment_metrics_data(environment, project)) if environment
|
||||
metrics_data.merge!(environment_metrics_data(environment)) if environment
|
||||
metrics_data.merge!(project_and_environment_metrics_data(project, environment)) if project && environment
|
||||
metrics_data.merge!(static_metrics_data)
|
||||
|
||||
|
|
@ -66,34 +66,20 @@ module EnvironmentsHelper
|
|||
}
|
||||
end
|
||||
|
||||
def environment_metrics_data(environment, project = nil)
|
||||
def environment_metrics_data(environment)
|
||||
return {} unless environment
|
||||
|
||||
{
|
||||
'metrics_dashboard_base_path' => metrics_dashboard_base_path(environment, project),
|
||||
'current_environment_name' => environment.name,
|
||||
'has_metrics' => environment.has_metrics?.to_s,
|
||||
'environment_state' => environment.state.to_s
|
||||
}
|
||||
end
|
||||
|
||||
def metrics_dashboard_base_path(environment, project)
|
||||
# This is needed to support our transition from environment scoped metric paths to project scoped.
|
||||
if project
|
||||
path = project_metrics_dashboard_path(project)
|
||||
|
||||
return path if request.path.include?(path)
|
||||
end
|
||||
|
||||
project_metrics_dashboard_path(project, environment: environment)
|
||||
end
|
||||
|
||||
def project_and_environment_metrics_data(project, environment)
|
||||
return {} unless project && environment
|
||||
|
||||
{
|
||||
'metrics_endpoint' => additional_metrics_project_environment_path(project, environment, format: :json),
|
||||
'dashboard_endpoint' => metrics_dashboard_project_environment_path(project, environment, format: :json),
|
||||
'deployments_endpoint' => project_environment_deployments_path(project, environment, format: :json),
|
||||
'operations_settings_path' => project_settings_operations_path(project),
|
||||
'can_access_operations_settings' => can?(current_user, :admin_operations, project).to_s,
|
||||
|
|
|
|||
|
|
@ -547,6 +547,14 @@ module ProjectsHelper
|
|||
project.ssh_url_to_repo
|
||||
end
|
||||
|
||||
def can_view_branch_rules?
|
||||
can?(current_user, :maintainer_access, @project)
|
||||
end
|
||||
|
||||
def can_push_code?
|
||||
current_user&.can?(:push_code, @project)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_merge_request_path(project, source_project, ref, merge_request)
|
||||
|
|
@ -892,10 +900,6 @@ def can_admin_group_clusters?(project)
|
|||
project.group && project.group.clusters.any? && can?(current_user, :admin_cluster, project.group)
|
||||
end
|
||||
|
||||
def can_view_branch_rules?
|
||||
can?(current_user, :maintainer_access, @project)
|
||||
end
|
||||
|
||||
def branch_rules_path
|
||||
project_settings_repository_path(@project, anchor: 'js-branch-rules')
|
||||
end
|
||||
|
|
|
|||
|
|
@ -33,10 +33,6 @@ module WebIdeButtonHelper
|
|||
can_view_pipeline_editor?(project) && path == project.ci_config_path_or_default
|
||||
end
|
||||
|
||||
def can_push_code?
|
||||
current_user&.can?(:push_code, @project)
|
||||
end
|
||||
|
||||
def fork?
|
||||
!project_fork.nil? && !can_push_code?
|
||||
end
|
||||
|
|
|
|||
|
|
@ -904,6 +904,16 @@ class Project < ApplicationRecord
|
|||
scope :for_group_and_its_ancestor_groups, ->(group) { where(namespace_id: group.self_and_ancestors.select(:id)) }
|
||||
scope :is_importing, -> { with_import_state.where(import_state: { status: %w[started scheduled] }) }
|
||||
|
||||
scope :without_created_and_owned_by_banned_user, -> do
|
||||
where_not_exists(
|
||||
Users::BannedUser.joins(
|
||||
'INNER JOIN project_authorizations ON project_authorizations.user_id = banned_users.user_id'
|
||||
).where('projects.creator_id = banned_users.user_id')
|
||||
.where('project_authorizations.project_id = projects.id')
|
||||
.where(project_authorizations: { access_level: Gitlab::Access::OWNER })
|
||||
)
|
||||
end
|
||||
|
||||
class << self
|
||||
# Searches for a list of projects based on the query given in `query`.
|
||||
#
|
||||
|
|
@ -3169,6 +3179,10 @@ class Project < ApplicationRecord
|
|||
pending_delete? || hidden?
|
||||
end
|
||||
|
||||
def created_and_owned_by_banned_user?
|
||||
creator.banned? && team.max_member_access(creator.id) == Gitlab::Access::OWNER
|
||||
end
|
||||
|
||||
def content_editor_on_issues_feature_flag_enabled?
|
||||
group&.content_editor_on_issues_feature_flag_enabled? || Feature.enabled?(:content_editor_on_issues, self)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -255,6 +255,10 @@ class ProjectPolicy < BasePolicy
|
|||
|
||||
condition(:namespace_catalog_available) { namespace_catalog_available? }
|
||||
|
||||
condition(:created_and_owned_by_banned_user, scope: :subject) do
|
||||
Feature.enabled?(:hide_projects_of_banned_users) && @subject.created_and_owned_by_banned_user?
|
||||
end
|
||||
|
||||
# `:read_project` may be prevented in EE, but `:read_project_for_iids` should
|
||||
# not.
|
||||
rule { guest | admin }.enable :read_project_for_iids
|
||||
|
|
@ -901,6 +905,10 @@ class ProjectPolicy < BasePolicy
|
|||
enable :read_model_experiments
|
||||
end
|
||||
|
||||
rule { ~admin & created_and_owned_by_banned_user }.policy do
|
||||
prevent :read_project
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def user_is_user?
|
||||
|
|
|
|||
|
|
@ -44,22 +44,10 @@ module AlertManagement
|
|||
project.incident_management_setting&.create_issue?
|
||||
end
|
||||
|
||||
def show_performance_dashboard_link?
|
||||
prometheus_alert.present?
|
||||
end
|
||||
|
||||
def incident_issues_link
|
||||
project_incidents_url(project)
|
||||
end
|
||||
|
||||
def performance_dashboard_link
|
||||
if environment
|
||||
metrics_project_environment_url(project, environment)
|
||||
else
|
||||
metrics_project_environments_url(project)
|
||||
end
|
||||
end
|
||||
|
||||
def email_title
|
||||
[environment&.name, query_title].compact.join(': ')
|
||||
end
|
||||
|
|
|
|||
|
|
@ -27,10 +27,6 @@ class EnvironmentEntity < Grape::Entity
|
|||
ops.merge(except: UNNECESSARY_ENTRIES_FOR_UPCOMING_DEPLOYMENT))
|
||||
end
|
||||
|
||||
expose :metrics_path, if: -> (*) { expose_metrics_path? } do |environment|
|
||||
metrics_project_environment_path(environment.project, environment)
|
||||
end
|
||||
|
||||
expose :environment_path do |environment|
|
||||
project_environment_path(environment.project, environment)
|
||||
end
|
||||
|
|
@ -101,10 +97,6 @@ class EnvironmentEntity < Grape::Entity
|
|||
def cluster
|
||||
deployment_platform.cluster
|
||||
end
|
||||
|
||||
def expose_metrics_path?
|
||||
!Feature.enabled?(:remove_monitor_metrics) && environment.has_metrics?
|
||||
end
|
||||
end
|
||||
|
||||
EnvironmentEntity.prepend_mod_with('EnvironmentEntity')
|
||||
|
|
|
|||
|
|
@ -15,10 +15,6 @@ class EnvironmentStatusEntity < Grape::Entity
|
|||
metrics_project_environment_deployment_path(es.project, es.environment, es.deployment)
|
||||
end
|
||||
|
||||
expose :metrics_monitoring_url, if: ->(*) { can_read_environment? } do |es|
|
||||
project_metrics_dashboard_path(es.project, environment: es.environment)
|
||||
end
|
||||
|
||||
expose :stop_url, if: ->(*) { can_stop_environment? } do |es|
|
||||
stop_project_environment_path(es.project, es.environment)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
%p.form-text.text-muted= _('URL must be percent-encoded if necessary.')
|
||||
.form-group
|
||||
= form.label :token, _('Secret token'), class: 'label-bold'
|
||||
= form.text_field :token, class: 'form-control gl-form-input'
|
||||
= form.text_field :token, class: 'form-control gl-form-input gl-max-w-48'
|
||||
%p.form-text.text-muted= _('Use this token to validate received payloads.')
|
||||
.form-group
|
||||
= form.label :url, _('Trigger'), class: 'label-bold'
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
- page_title @hook.pluralized_name
|
||||
|
||||
.row.gl-mt-3
|
||||
.col-lg-4
|
||||
= render 'shared/web_hooks/title_and_docs', hook: @hook
|
||||
.gl-mt-5
|
||||
= render 'shared/web_hooks/title_and_docs', hook: @hook
|
||||
|
||||
.col-lg-8.gl-mb-3
|
||||
.gl-mb-3
|
||||
= gitlab_ui_form_for @hook, as: :hook, url: admin_hooks_path do |f|
|
||||
= render partial: 'form', locals: { form: f, hook: @hook }
|
||||
= f.submit _('Add system hook'), pajamas_button: true
|
||||
|
|
|
|||
|
|
@ -25,7 +25,3 @@
|
|||
- if @alert.show_incident_issues_link?
|
||||
%p
|
||||
= link_to(_('View incident issues.'), @alert.incident_issues_link)
|
||||
|
||||
- if @alert.show_performance_dashboard_link?
|
||||
%p
|
||||
= link_to(_('View performance dashboard.'), @alert.performance_dashboard_link)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,3 @@
|
|||
<% if @alert.show_incident_issues_link? %>
|
||||
<%= _('View incident issues.') %> <%= @alert.incident_issues_link %>
|
||||
<% end %>
|
||||
|
||||
<% if @alert.show_performance_dashboard_link? %>
|
||||
<%= _('View the performance dashboard at') %> <%= @alert.performance_dashboard_link %>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -20,10 +20,12 @@
|
|||
%li= _('Webhooks')
|
||||
%li= _('Any encrypted tokens')
|
||||
- if project.export_status == :finished
|
||||
= link_to _('Download export'), download_export_project_path(project),
|
||||
rel: 'nofollow', download: '', method: :get, class: "btn gl-button btn-default", data: { qa_selector: 'download_export_link' }
|
||||
= link_to _('Generate new export'), generate_new_export_project_path(project),
|
||||
method: :post, class: "btn gl-button btn-default"
|
||||
= render Pajamas::ButtonComponent.new(href: download_export_project_path(project),
|
||||
method: :get,
|
||||
button_options: { ref: 'nofollow', download: '', data: { qa_selector: 'download_export_link' } }) do
|
||||
= _('Download export')
|
||||
= render Pajamas::ButtonComponent.new(href: generate_new_export_project_path(project), method: :post) do
|
||||
= _('Generate new export')
|
||||
- else
|
||||
= link_to _('Export project'), export_project_path(project),
|
||||
method: :post, class: "btn gl-button btn-default", data: { qa_selector: 'export_project_link' }
|
||||
= render Pajamas::ButtonComponent.new(href: export_project_path(project), method: :post, button_options: { data: { qa_selector: 'export_project_link' } }) do
|
||||
= _('Export project')
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
- add_page_specific_style 'page_bundles/branches'
|
||||
- page_title _('Branches')
|
||||
- add_to_breadcrumbs(_('Repository'), project_tree_path(@project))
|
||||
- can_access_branch_rules = can?(current_user, :maintainer_access, @project)
|
||||
- can_push_code = (can? current_user, :push_code, @project)
|
||||
|
||||
-# Possible values for variables passed down from the projects/branches_controller.rb
|
||||
-#
|
||||
|
|
@ -24,11 +22,11 @@
|
|||
sorted_by: @sort }
|
||||
}
|
||||
|
||||
- if can_access_branch_rules
|
||||
- if can_view_branch_rules?
|
||||
= link_to project_settings_repository_path(@project, anchor: 'js-branch-rules'), class: 'gl-button btn btn-default' do
|
||||
= s_('Branches|View branch rules')
|
||||
|
||||
- if can_push_code
|
||||
- if can_push_code?
|
||||
= link_to new_project_branch_path(@project), class: 'gl-button btn btn-confirm' do
|
||||
= s_('Branches|New branch')
|
||||
.js-delete-merged-branches.gl-w-7{ data: {
|
||||
|
|
@ -38,7 +36,7 @@
|
|||
|
||||
= render_if_exists 'projects/commits/mirror_status'
|
||||
|
||||
- if can_access_branch_rules
|
||||
- if can_view_branch_rules?
|
||||
= render 'branch_rules_info'
|
||||
|
||||
.js-branch-list{ data: { diverging_counts_endpoint: diverging_commit_counts_namespace_project_branches_path(@project.namespace, @project, format: :json), default_branch: @project.default_branch } }
|
||||
|
|
|
|||
|
|
@ -2,11 +2,10 @@
|
|||
- page_title _('Webhooks')
|
||||
- @force_desktop_expanded_sidebar = true
|
||||
|
||||
.row.gl-mt-3.js-search-settings-section
|
||||
.col-lg-4
|
||||
= render 'shared/web_hooks/title_and_docs', hook: @hook
|
||||
.gl-mt-3.js-search-settings-section
|
||||
= render 'shared/web_hooks/title_and_docs', hook: @hook
|
||||
|
||||
.col-lg-8.gl-mb-3
|
||||
.gl-mb-3
|
||||
= gitlab_ui_form_for @hook, as: :hook, url: polymorphic_path([@project, :hooks]), html: { class: 'js-webhook-form' } do |f|
|
||||
= render partial: 'shared/web_hooks/form', locals: { form: f, hook: @hook }
|
||||
= f.submit _('Add webhook'), pajamas_button: true, data: { qa_selector: "create_webhook_button" }
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
- release_btn_text = s_('TagsPage|Create release')
|
||||
- release_btn_path = new_project_release_path(project, tag_name: tag.name)
|
||||
- option_css_classes = local_assigns.fetch(:option_css_classes, '')
|
||||
- css_classes = "btn gl-button btn-default btn-icon btn-edit has-tooltip #{option_css_classes}"
|
||||
- if release
|
||||
- release_btn_text = s_('TagsPage|Edit release')
|
||||
- release_btn_path = edit_project_release_path(project, release)
|
||||
= link_to release_btn_path, class: css_classes do
|
||||
= render Pajamas::ButtonComponent.new(href: release_btn_path, button_options: { class: option_css_classes }) do
|
||||
= release_btn_text
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
= render "layouts/one_trust"
|
||||
= render "layouts/bizible"
|
||||
= render "layouts/google_tag_manager_body"
|
||||
|
||||
.row.gl-flex-grow-1
|
||||
.d-flex.gl-flex-direction-column.gl-align-items-center.gl-w-full.gl-px-5.gl-pb-5
|
||||
.edit-profile.login-page.d-flex.flex-column.gl-align-items-center
|
||||
|
|
|
|||
|
|
@ -1,15 +1,13 @@
|
|||
- file_hooks = Gitlab::FileHook.files
|
||||
|
||||
.row.gl-mt-3
|
||||
.col-lg-4
|
||||
%h4.gl-mt-0
|
||||
= _('File Hooks')
|
||||
%p
|
||||
= _('File hooks are similar to system hooks but are executed as files instead of sending data to a URL.')
|
||||
= link_to _('For more information, see the File Hooks documentation.'), help_page_path('administration/file_hooks')
|
||||
.gl-mt-7
|
||||
%h4.gl-my-0
|
||||
= _('File Hooks')
|
||||
%p.gl-text-secondary
|
||||
= _('File hooks are similar to system hooks but are executed as files instead of sending data to a URL.')
|
||||
= link_to _('For more information, see the File Hooks documentation.'), help_page_path('administration/file_hooks')
|
||||
|
||||
|
||||
.col-lg-8.gl-mb-3
|
||||
.gl-mb-3
|
||||
- if file_hooks.any?
|
||||
= render Pajamas::CardComponent.new do |c|
|
||||
- c.with_header do
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
.js-vue-webhook-form{ data: webhook_form_data(hook) }
|
||||
.form-group
|
||||
= form.label :token, s_('Webhooks|Secret token'), class: 'label-bold'
|
||||
= form.password_field :token, value: hook.masked_token, autocomplete: 'new-password', class: 'form-control gl-form-input'
|
||||
= form.password_field :token, value: hook.masked_token, autocomplete: 'new-password', class: 'form-control gl-form-input gl-max-w-48'
|
||||
%p.form-text.text-muted
|
||||
- code_start = '<code>'.html_safe
|
||||
- code_end = '</code>'.html_safe
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
- webhooks_link_start = '<a href="%{url}">'.html_safe % { url: help_page_path(hook.help_path) }
|
||||
|
||||
%h4.gl-mt-0
|
||||
%h4.gl-my-0
|
||||
= page_title
|
||||
|
||||
- if @project
|
||||
- integrations_link_start = '<a href="%{url}">'.html_safe % { url: scoped_integrations_path(project: @project) }
|
||||
%p= _("%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook.").html_safe % { webhooks_link_start: webhooks_link_start, webhook_type: hook.pluralized_name, integrations_link_start: integrations_link_start, link_end: '</a>'.html_safe }
|
||||
%p.gl-text-secondary= _("%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook.").html_safe % { webhooks_link_start: webhooks_link_start, webhook_type: hook.pluralized_name, integrations_link_start: integrations_link_start, link_end: '</a>'.html_safe }
|
||||
- else
|
||||
%p= _("%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project.").html_safe % { webhooks_link_start: webhooks_link_start, webhook_type: hook.pluralized_name, link_end: '</a>'.html_safe }
|
||||
%p.gl-text-secondary= _("%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project.").html_safe % { webhooks_link_start: webhooks_link_start, webhook_type: hook.pluralized_name, link_end: '</a>'.html_safe }
|
||||
|
|
|
|||
|
|
@ -13,12 +13,10 @@
|
|||
.col-12.col-md-10.col-lg-8.gl-my-6
|
||||
.gl-display-flex
|
||||
%ol.breadcrumb.gl-breadcrumb-list.gl-mb-4
|
||||
%li.breadcrumb-item.gl-breadcrumb-item
|
||||
%li.gl-breadcrumb-item
|
||||
= link_to project_path(@user.user_project) do
|
||||
= @user.username
|
||||
%span.gl-breadcrumb-separator
|
||||
= sprite_icon("chevron-right", size: 16)
|
||||
%li.breadcrumb-item.gl-breadcrumb-item
|
||||
%li.gl-breadcrumb-item
|
||||
= link_to @user.user_readme.path, @user.user_project.readme_url
|
||||
- if current_user == @user
|
||||
.gl-ml-auto
|
||||
|
|
|
|||
|
|
@ -217,6 +217,9 @@ module Gitlab
|
|||
sharedSecret
|
||||
)
|
||||
|
||||
# This config option can be removed after Rails 7.1 by https://gitlab.com/gitlab-org/gitlab/-/issues/416270
|
||||
config.active_support.use_rfc4122_namespaced_uuids = true
|
||||
|
||||
# Enable escaping HTML in JSON.
|
||||
config.active_support.escape_html_entities_in_json = true
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
---
|
||||
name: ai_chat_history_context
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/122920
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/414606
|
||||
milestone: '16.1'
|
||||
name: hide_projects_of_banned_users
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121488
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/412621
|
||||
milestone: '16.2'
|
||||
type: development
|
||||
group: group::ai-enablement
|
||||
group: group::anti-abuse
|
||||
default_enabled: false
|
||||
|
|
@ -246,7 +246,6 @@ InitializerConnections.raise_if_new_database_connection do
|
|||
end
|
||||
|
||||
get :metrics_dashboard
|
||||
get :'/prometheus/api/v1/*proxy_path', to: 'clusters#prometheus_proxy', as: :prometheus_api
|
||||
get :cluster_status, format: :json
|
||||
delete :clear_cache
|
||||
end
|
||||
|
|
|
|||
|
|
@ -29,10 +29,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
|
|||
# Use this scope for all new project routes.
|
||||
scope '-' do
|
||||
get 'archive/*id', format: true, constraints: { format: Gitlab::PathRegex.archive_formats_regex, id: /.+?/ }, to: 'repositories#archive', as: 'archive'
|
||||
get 'metrics(/:dashboard_path)', constraints: { dashboard_path: /.+\.yml/ },
|
||||
to: 'metrics_dashboard#show', as: :metrics_dashboard, format: false
|
||||
get 'metrics(/:dashboard_path)/panel/new', constraints: { dashboard_path: /.+\.yml/ },
|
||||
to: 'metrics_dashboard#show', as: :new_metrics_dashboard, format: false
|
||||
|
||||
namespace :metrics, module: :metrics do
|
||||
namespace :dashboards do
|
||||
|
|
@ -330,9 +326,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
|
|||
post :stop
|
||||
post :cancel_auto_stop
|
||||
get :terminal
|
||||
get :metrics
|
||||
get :additional_metrics
|
||||
get :metrics_dashboard
|
||||
|
||||
# This route is also defined in gitlab-workhorse. Make sure to update accordingly.
|
||||
get '/terminal.ws/authorize', to: 'environments#terminal_websocket_authorize', format: false
|
||||
|
|
@ -343,7 +336,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
|
|||
end
|
||||
|
||||
collection do
|
||||
get :metrics, action: :metrics_redirect
|
||||
get :folder, path: 'folders/*id', constraints: { format: /(html|json)/ }
|
||||
get :search
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
#
|
||||
# REQUIRED FIELDS
|
||||
#
|
||||
- title: "Accessibility Testing is deprecated" # (required) Clearly explain the change, or planned change. For example, "The `confidential` field for a `Note` is deprecated" or "CI/CD job names will be limited to 250 characters."
|
||||
announcement_milestone: "15.9" # (required) The milestone when this feature was first announced as deprecated.
|
||||
removal_milestone: "17.0" # (required) The milestone when this feature is planned to be removed
|
||||
breaking_change: true # (required) Change to false if this is not a breaking change.
|
||||
reporter: jocelynjane # (required) GitLab username of the person reporting the change
|
||||
stage: Verify # (required) String value of the stage that the feature was created in. e.g., Growth
|
||||
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/390424 # (required) Link to the deprecation issue in GitLab
|
||||
body: | # (required) Do not modify this line, instead modify the lines below.
|
||||
Due to low customer usage, Accessibility Testing is deprecated and will be removed. There is no planned replacement and users should stop using Accessibility Testing before GitLab 17.0.
|
||||
#
|
||||
# OPTIONAL END OF SUPPORT FIELDS
|
||||
#
|
||||
# If an End of Support period applies, the announcement should be shared with GitLab Support
|
||||
# in the `#spt_managers` channel in Slack, and mention `@gitlab-com/support` in this MR.
|
||||
#
|
||||
end_of_support_milestone: # (optional) Use "XX.YY" format. The milestone when support for this feature will end.
|
||||
#
|
||||
# OTHER OPTIONAL FIELDS
|
||||
#
|
||||
tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
|
||||
documentation_url: https://docs.gitlab.com/ee/ci/testing/accessibility_testing.html # (optional) This is a link to the current documentation page
|
||||
image_url: # (optional) This is a link to a thumbnail image depicting the feature
|
||||
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
#
|
||||
# REQUIRED FIELDS
|
||||
#
|
||||
- title: "Browser Performance Testing is deprecated" # (required) Clearly explain the change, or planned change. For example, "The `confidential` field for a `Note` is deprecated" or "CI/CD job names will be limited to 250 characters."
|
||||
announcement_milestone: "15.9" # (required) The milestone when this feature was first announced as deprecated.
|
||||
removal_milestone: "17.0" # (required) The milestone when this feature is planned to be removed
|
||||
breaking_change: true # (required) Change to false if this is not a breaking change.
|
||||
reporter: jocelynjane # (required) GitLab username of the person reporting the change
|
||||
stage: Verify # (required) String value of the stage that the feature was created in. e.g., Growth
|
||||
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/388719 # (required) Link to the deprecation issue in GitLab
|
||||
body: | # (required) Do not modify this line, instead modify the lines below.
|
||||
Due to limited customer usage, Browser Performance Testing is deprecated and will be removed. There is no planned replacement and users should stop using Browser Performance Testing before GitLab 17.0.
|
||||
#
|
||||
# OPTIONAL END OF SUPPORT FIELDS
|
||||
#
|
||||
# If an End of Support period applies, the announcement should be shared with GitLab Support
|
||||
# in the `#spt_managers` channel in Slack, and mention `@gitlab-com/support` in this MR.
|
||||
#
|
||||
end_of_support_milestone: # (optional) Use "XX.YY" format. The milestone when support for this feature will end.
|
||||
#
|
||||
# OTHER OPTIONAL FIELDS
|
||||
#
|
||||
tiers: Premium # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
|
||||
documentation_url: https://docs.gitlab.com/ee/ci/testing/browser_performance_testing.html # (optional) This is a link to the current documentation page
|
||||
image_url: # (optional) This is a link to a thumbnail image depicting the feature
|
||||
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
#
|
||||
# REQUIRED FIELDS
|
||||
#
|
||||
- title: "Load Performance Testing is deprecated" # (required) Clearly explain the change, or planned change. For example, "The `confidential` field for a `Note` is deprecated" or "CI/CD job names will be limited to 250 characters."
|
||||
announcement_milestone: "15.9" # (required) The milestone when this feature was first announced as deprecated.
|
||||
removal_milestone: "17.0" # (required) The milestone when this feature is planned to be removed
|
||||
breaking_change: true # (required) Change to false if this is not a breaking change.
|
||||
reporter: jocelynjane # (required) GitLab username of the person reporting the change
|
||||
stage: Verify # (required) String value of the stage that the feature was created in. e.g., Growth
|
||||
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/388723 # (required) Link to the deprecation issue in GitLab
|
||||
body: | # (required) Do not modify this line, instead modify the lines below.
|
||||
Due to low customer usage, Load Performance Testing is deprecated and will be removed. There is no planned replacement and users should stop using Load Performance Testing before GitLab 17.0.
|
||||
#
|
||||
# OPTIONAL END OF SUPPORT FIELDS
|
||||
#
|
||||
# If an End of Support period applies, the announcement should be shared with GitLab Support
|
||||
# in the `#spt_managers` channel in Slack, and mention `@gitlab-com/support` in this MR.
|
||||
#
|
||||
end_of_support_milestone: # (optional) Use "XX.YY" format. The milestone when support for this feature will end.
|
||||
#
|
||||
# OTHER OPTIONAL FIELDS
|
||||
#
|
||||
tiers: Premium # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
|
||||
documentation_url: https://docs.gitlab.com/ee/ci/testing/load_performance_testing.html # (optional) This is a link to the current documentation page
|
||||
image_url: # (optional) This is a link to a thumbnail image depicting the feature
|
||||
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateIndexForVulnerabilityReadsOnCommonProjectFilters < Gitlab::Database::Migration[2.1]
|
||||
disable_ddl_transaction!
|
||||
|
||||
INDEX_NAME = 'index_project_vulnerability_reads_common_finder_query_desc'
|
||||
|
||||
def up
|
||||
add_concurrent_index :vulnerability_reads,
|
||||
[:project_id, :state, :report_type, :severity, :vulnerability_id],
|
||||
order: { severity: :desc, vulnerability_id: :desc },
|
||||
name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index_by_name :vulnerability_reads, INDEX_NAME
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
7060d1ed7be6fce2e398d9ac042d6e67826742e639df8eee43245d66b8b87ea3
|
||||
|
|
@ -32410,6 +32410,8 @@ CREATE INDEX index_project_topics_on_topic_id ON project_topics USING btree (top
|
|||
|
||||
CREATE UNIQUE INDEX index_project_user_callouts_feature ON user_project_callouts USING btree (user_id, feature_name, project_id);
|
||||
|
||||
CREATE INDEX index_project_vulnerability_reads_common_finder_query_desc ON vulnerability_reads USING btree (project_id, state, report_type, severity DESC, vulnerability_id DESC);
|
||||
|
||||
CREATE UNIQUE INDEX index_project_wiki_repositories_on_project_id ON project_wiki_repositories USING btree (project_id);
|
||||
|
||||
CREATE INDEX index_projects_aimed_for_deletion ON projects USING btree (marked_for_deletion_at) WHERE ((marked_for_deletion_at IS NOT NULL) AND (pending_delete = false));
|
||||
|
|
|
|||
|
|
@ -303,6 +303,7 @@ Parameters:
|
|||
| `simple` | boolean | no | Return only limited fields for each project. This is a no-op without authentication where only simple fields are returned. |
|
||||
| `owned` | boolean | no | Limit by projects owned by the current user |
|
||||
| `starred` | boolean | no | Limit by projects starred by the current user |
|
||||
| `topic` | string | no | Return projects matching the topic |
|
||||
| `with_issues_enabled` | boolean | no | Limit by projects with issues feature enabled. Default is `false` |
|
||||
| `with_merge_requests_enabled` | boolean | no | Limit by projects with merge requests feature enabled. Default is `false` |
|
||||
| `with_shared` | boolean | no | Include projects shared to this group. Default is `true` |
|
||||
|
|
|
|||
|
|
@ -510,7 +510,7 @@ Parameters:
|
|||
| `auditor` **(PREMIUM)** | No | User is an auditor. Valid values are `true` or `false`. Defaults to false. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/366404) in GitLab 15.3. |
|
||||
| `avatar` | No | Image file for user's avatar |
|
||||
| `bio` | No | User's biography |
|
||||
| `can_create_group` | No | User can create groups - true or false |
|
||||
| `can_create_group` | No | User can create top-level groups - true or false |
|
||||
| `color_scheme_id` | No | User's color scheme for the file viewer (for more information, see the [user preference documentation](../user/profile/preferences.md#syntax-highlighting-theme)) |
|
||||
| `email` | Yes | Email |
|
||||
| `extern_uid` | No | External UID |
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
status: proposed
|
||||
creation-date: "2023-03-15"
|
||||
authors: [ "@furkanayhan" ]
|
||||
owners: [ "@furkanayhan" ]
|
||||
coach: "@grzesiek"
|
||||
approvers: [ "@jreporter", "@cheryl.li" ]
|
||||
owning-stage: "~devops::verify"
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ feature-full.
|
|||
|Total time chart|Yes|No|No|
|
||||
|Task by type chart|Yes|No|No|
|
||||
|DORA Metrics|Yes|Yes|No|
|
||||
|Cycle time and lead time summary (Key metrics)|Yes|Yes|No|
|
||||
|New issues, commits and deploys (Key metrics)|Yes, excluding commits|Yes|Yes|
|
||||
|Cycle time and lead time summary (Lifecycle metrics)|Yes|Yes|No|
|
||||
|New issues, commits and deploys (Lifecycle metrics)|Yes, excluding commits|Yes|Yes|
|
||||
|Uses aggregated backend|Yes|No|No|
|
||||
|Date filter behavior|Filters items [finished within the date range](https://gitlab.com/groups/gitlab-org/-/epics/6046)|Filters items by creation date.|Filters items by creation date.|
|
||||
|Authorization|At least reporter|At least reporter|Can be public.|
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ To start, we will find the project we want to work on.
|
|||
|
||||

|
||||
|
||||
## Customize the sidebar
|
||||
## Pin frequently used items
|
||||
|
||||
You can pin menu items if you tend to use them frequently.
|
||||
|
||||
|
|
@ -76,6 +76,9 @@ The item is displayed in the **Pinned** section:
|
|||
|
||||

|
||||
|
||||
NOTE:
|
||||
The items you pin while you're viewing a project are different than the items you pin while viewing a group.
|
||||
|
||||
## Use a more focused view
|
||||
|
||||
On the left sidebar, you can also choose a more focused view into the areas you have access to.
|
||||
|
|
|
|||
|
|
@ -50,20 +50,6 @@ For deprecation reviewers (Technical Writers only):
|
|||
|
||||
<div class="deprecation breaking-change" data-milestone="17.0">
|
||||
|
||||
### Accessibility Testing is deprecated
|
||||
|
||||
<div class="deprecation-notes">
|
||||
- Announced in: GitLab <span class="milestone">15.9</span>
|
||||
- This is a [breaking change](https://docs.gitlab.com/ee/update/terminology.html#breaking-change).
|
||||
- To discuss this change or learn more, see the [deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/390424).
|
||||
</div>
|
||||
|
||||
Due to low customer usage, Accessibility Testing is deprecated and will be removed. There is no planned replacement and users should stop using Accessibility Testing before GitLab 17.0.
|
||||
|
||||
</div>
|
||||
|
||||
<div class="deprecation breaking-change" data-milestone="17.0">
|
||||
|
||||
### Atlassian Crowd OmniAuth provider
|
||||
|
||||
<div class="deprecation-notes">
|
||||
|
|
@ -97,20 +83,6 @@ Because Cloud Native Buildpacks do not support automatic testing, the Auto Test
|
|||
|
||||
<div class="deprecation breaking-change" data-milestone="17.0">
|
||||
|
||||
### Browser Performance Testing is deprecated
|
||||
|
||||
<div class="deprecation-notes">
|
||||
- Announced in: GitLab <span class="milestone">15.9</span>
|
||||
- This is a [breaking change](https://docs.gitlab.com/ee/update/terminology.html#breaking-change).
|
||||
- To discuss this change or learn more, see the [deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/388719).
|
||||
</div>
|
||||
|
||||
Due to limited customer usage, Browser Performance Testing is deprecated and will be removed. There is no planned replacement and users should stop using Browser Performance Testing before GitLab 17.0.
|
||||
|
||||
</div>
|
||||
|
||||
<div class="deprecation breaking-change" data-milestone="17.0">
|
||||
|
||||
### CiRunner.projects default sort is changing to `id_desc`
|
||||
|
||||
<div class="deprecation-notes">
|
||||
|
|
@ -333,20 +305,6 @@ In GitLab 17.0, the `DISABLED_WITH_OVERRIDE` value of the `SharedRunnersSetting`
|
|||
|
||||
<div class="deprecation breaking-change" data-milestone="17.0">
|
||||
|
||||
### Load Performance Testing is deprecated
|
||||
|
||||
<div class="deprecation-notes">
|
||||
- Announced in: GitLab <span class="milestone">15.9</span>
|
||||
- This is a [breaking change](https://docs.gitlab.com/ee/update/terminology.html#breaking-change).
|
||||
- To discuss this change or learn more, see the [deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/388723).
|
||||
</div>
|
||||
|
||||
Due to low customer usage, Load Performance Testing is deprecated and will be removed. There is no planned replacement and users should stop using Load Performance Testing before GitLab 17.0.
|
||||
|
||||
</div>
|
||||
|
||||
<div class="deprecation breaking-change" data-milestone="17.0">
|
||||
|
||||
### Maintainer role providing the ability to change Package settings using GraphQL API
|
||||
|
||||
<div class="deprecation-notes">
|
||||
|
|
|
|||
|
|
@ -256,8 +256,9 @@ Users can also be activated using the [GitLab API](../../api/users.md#activate-u
|
|||
> - Ban and unban users [generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/327353) in GitLab 14.8. Feature flag `ban_user_feature_flag` removed.
|
||||
> - Hiding merge requests of banned users [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/107836) in GitLab 15.8 [with a flag](../../administration/feature_flags.md) named `hide_merge_requests_from_banned_users`. Disabled by default.
|
||||
> - Hiding comments of banned users [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/112973) in GitLab 15.11 [with a flag](../../administration/feature_flags.md) named `hidden_notes`. Disabled by default.
|
||||
> - Hiding projects of banned users [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121488) in GitLab 16.2 [with a flag](../../administration/feature_flags.md) named `hide_projects_of_banned_users`. Disabled by default.
|
||||
|
||||
GitLab administrators can ban and unban users. Banned users are blocked, and their issues, merge requests, and comments are hidden.
|
||||
GitLab administrators can ban and unban users. Banned users are blocked, and their projects, issues, merge requests, and comments are hidden.
|
||||
|
||||
### Ban a user
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ To view the value streams dashboard:
|
|||
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project or group.
|
||||
1. Select **Analyze > Value stream analytics**.
|
||||
1. Below the **Filter results** text box, in the **Key metrics** row, select **Value Streams Dashboard / DORA**.
|
||||
1. Below the **Filter results** text box, in the **Lifecycle metrics** row, select **Value Streams Dashboard / DORA**.
|
||||
1. Optional. To open the new page, append this path `/analytics/dashboards/value_streams_dashboard` to the group URL
|
||||
(for example, `https://gitlab.com/groups/gitlab-org/-/analytics/dashboards/value_streams_dashboard`).
|
||||
|
||||
|
|
@ -142,8 +142,8 @@ panels:
|
|||
| Lead time for changes | The time to successfully deliver a commit into production. This metric reflects the efficiency of CI/CD pipelines. | [Lead time tab](https://gitlab.com/groups/gitlab-org/-/analytics/ci_cd?tab=lead-time) | [Lead time for changes](dora_metrics.md#lead-time-for-changes) | `lead_time_for_changes` |
|
||||
| Time to restore service | The time it takes an organization to recover from a failure in production. | [Time to restore service tab](https://gitlab.com/groups/gitlab-org/-/analytics/ci_cd?tab=time-to-restore-service) | [Time to restore service](dora_metrics.md#time-to-restore-service) | `time_to_restore_service` |
|
||||
| Change failure rate | Percentage of deployments that cause an incident in production. | [Change failure rate tab](https://gitlab.com/groups/gitlab-org/-/analytics/ci_cd?tab=change-failure-rate) | [Change failure rate](dora_metrics.md#change-failure-rate) | `change_failure_rate` |
|
||||
| Lead time | Median time from issue created to issue closed. | [Value Stream Analytics](https://gitlab.com/groups/gitlab-org/-/analytics/value_stream_analytics) | [View the lead time and cycle time for issues](../group/value_stream_analytics/index.md#key-metrics) | `lead_time` |
|
||||
| Cycle time | Median time from the earliest commit of a linked issue's merge request to when that issue is closed. | [VSA overview](https://gitlab.com/groups/gitlab-org/-/analytics/value_stream_analytics) | [View the lead time and cycle time for issues](../group/value_stream_analytics/index.md#key-metrics) | `cycle_time` |
|
||||
| Lead time | Median time from issue created to issue closed. | [Value Stream Analytics](https://gitlab.com/groups/gitlab-org/-/analytics/value_stream_analytics) | [View the lead time and cycle time for issues](../group/value_stream_analytics/index.md#lifecycle-metrics) | `lead_time` |
|
||||
| Cycle time | Median time from the earliest commit of a linked issue's merge request to when that issue is closed. | [VSA overview](https://gitlab.com/groups/gitlab-org/-/analytics/value_stream_analytics) | [View the lead time and cycle time for issues](../group/value_stream_analytics/index.md#lifecycle-metrics) | `cycle_time` |
|
||||
| New issues | Number of new issues created. | [Issue Analytics](https://gitlab.com/groups/gitlab-org/-/issues_analytics) | Issue analytics [for projects](issue_analytics.md) and [for groups](../../user/group/issues_analytics/index.md) | `issues` |
|
||||
| Closed issues | Number of issues closed by month. | [Value Stream Analytics](https://gitlab.com/groups/gitlab-org/-/analytics/value_stream_analytics) | [Value Stream Analytics](../group/value_stream_analytics/index.md) | `issues_completed` |
|
||||
| Number of deploys | Total number of deploys to production. | [Merge Request Analytics](https://gitlab.com/gitlab-org/gitlab/-/analytics/merge_request_analytics) | [Merge request analytics](merge_request_analytics.md) | `deploys` |
|
||||
|
|
|
|||
|
|
@ -396,11 +396,10 @@ convert the information to XML. An example SAML response is shown here.
|
|||
By default, users provisioned with SAML or SCIM are sent a verification email to verify their identity. Instead, you can
|
||||
[configure GitLab with a custom domain](../../enterprise_user/index.md#set-up-a-verified-domain) and GitLab
|
||||
automatically confirms user accounts. Users still receive an
|
||||
[enterprise user](../../enterprise_user/index.md) welcome email. Confirmation is
|
||||
bypassed for users:
|
||||
[enterprise user](../../enterprise_user/index.md) welcome email. Confirmation is bypassed if both of the following are true:
|
||||
|
||||
- That are provisioned with SAML or SCIM.
|
||||
- That have an email address that belongs to the verified domain.
|
||||
- The user is provisioned with SAML or SCIM.
|
||||
- The user has an email address that belongs to the verified domain.
|
||||
|
||||
### Block user access
|
||||
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@ Value stream analytics offers different features at the project and group level
|
|||
|Total time chart|Yes|Yes|No|
|
||||
|Task by type chart|Yes|No|No|
|
||||
|DORA Metrics|Yes|Yes|No|
|
||||
|Cycle time and lead time summary (Key metrics)|Yes|Yes|No|
|
||||
|New issues, commits, and deploys (Key metrics)|Yes, excluding commits|Yes|Yes|
|
||||
|Cycle time and lead time summary (Lifecycle metrics)|Yes|Yes|No|
|
||||
|New issues, commits, and deploys (Lifecycle metrics)|Yes, excluding commits|Yes|Yes|
|
||||
|Uses aggregated backend|Yes|Yes|No|
|
||||
|Date filter behavior|Filters items [finished within the date range](https://gitlab.com/groups/gitlab-org/-/epics/6046)|Filters items by creation date.|Filters items by creation date.|
|
||||
|Authorization|At least reporter|At least reporter|Can be public|
|
||||
|
|
@ -253,9 +253,9 @@ For the "Tasks by type" chart, only the Date range and Project selector filters
|
|||
|
||||
The **Overview** page in value stream analytics displays key metrics of the DevSecOps lifecycle performance for projects and groups.
|
||||
|
||||
### Key metrics
|
||||
### Lifecycle metrics
|
||||
|
||||
Value stream analytics includes the following key metrics:
|
||||
Value stream analytics includes the following lifecycle metrics:
|
||||
|
||||
- **Lead time**: Median time from when the issue was created to when it was closed.
|
||||
- **Cycle time**: Median time from first commit to issue closed. GitLab measures cycle time from the earliest commit of a
|
||||
|
|
@ -290,21 +290,21 @@ NOTE:
|
|||
In GitLab 13.9 and later, deployment frequency metrics are calculated based on when the deployment was finished.
|
||||
In GitLab 13.8 and earlier, deployment frequency metrics are calculated based on when the deployment was created.
|
||||
|
||||
## View key and DORA metrics
|
||||
## View lifecycle and DORA metrics
|
||||
|
||||
Prerequisite:
|
||||
|
||||
- To view deployment metrics, you must have a
|
||||
[production environment configured](#how-value-stream-analytics-identifies-the-production-environment).
|
||||
|
||||
To view key lifecycle metrics:
|
||||
To view lifecycle metrics:
|
||||
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project or group.
|
||||
1. Select **Analyze > Value stream analytics**.
|
||||
Key metrics display below the **Filter results** text box.
|
||||
Lifecycle metrics display below the **Filter results** text box.
|
||||
1. Optional. Filter the results:
|
||||
1. Select the **Filter results** text box.
|
||||
Based on the filter you select, the dashboard automatically aggregates key metrics and displays the status of the value stream.
|
||||
Based on the filter you select, the dashboard automatically aggregates lifecycle metrics and displays the status of the value stream.
|
||||
1. Select a parameter.
|
||||
1. Select a value or enter text to refine the results.
|
||||
1. To adjust the date range:
|
||||
|
|
@ -315,7 +315,7 @@ To view the [Value Streams Dashboard](../../analytics/value_streams_dashboard.md
|
|||
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project or group.
|
||||
1. Select **Analyze > Value stream analytics**.
|
||||
1. Below the **Filter results** text box, in the **Key metrics** row, select **Value Streams Dashboard / DORA**.
|
||||
1. Below the **Filter results** text box, in the **Lifecycle metrics** row, select **Value Streams Dashboard / DORA**.
|
||||
1. Optional. To open the new page, append this path `/analytics/dashboards/value_streams_dashboard` to the group URL
|
||||
(for example, `https://gitlab.com/groups/gitlab-org/-/analytics/dashboards/value_streams_dashboard`).
|
||||
|
||||
|
|
|
|||
|
|
@ -95,12 +95,7 @@ you can create your project first and access it under `http(s)://namespace.examp
|
|||
## Enable unique domains
|
||||
|
||||
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/9347) in GitLab 15.9 [with a flag](../../../administration/feature_flags.md) named `pages_unique_domain`. Disabled by default.
|
||||
> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/388151) in GitLab 15.11.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is not available. To make it available,
|
||||
ask an administrator to [enable the feature flag](../../../administration/feature_flags.md) named `pages_unique_domain`.
|
||||
On GitLab.com, by default this feature is available.
|
||||
> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/388151) in GitLab 15.11.
|
||||
|
||||
By default, every project in a group shares the same domain, for example, `group.gitlab.io`. This means that cookies are also shared for all projects in a group.
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ module API
|
|||
included do
|
||||
helpers do
|
||||
params :with_custom_attributes do
|
||||
optional :with_custom_attributes, type: Boolean, default: false, desc: 'Include custom attributes in the response'
|
||||
optional :with_custom_attributes, type: ::Grape::API::Boolean, default: false, desc: 'Include custom attributes in the response'
|
||||
|
||||
optional :custom_attributes, type: Hash,
|
||||
desc: 'Filter with custom attributes'
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ module API
|
|||
{
|
||||
required: false,
|
||||
name: :notify_only_broken_pipelines,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Send notifications for broken pipelines'
|
||||
}
|
||||
].freeze
|
||||
|
|
@ -129,85 +129,85 @@ module API
|
|||
{
|
||||
required: false,
|
||||
name: :commit_events,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Enable notifications for commit_events'
|
||||
},
|
||||
{
|
||||
required: false,
|
||||
name: :push_events,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Enable notifications for push_events'
|
||||
},
|
||||
{
|
||||
required: false,
|
||||
name: :issues_events,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Enable notifications for issues_events'
|
||||
},
|
||||
{
|
||||
required: false,
|
||||
name: :incident_events,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Enable notifications for incident_events'
|
||||
},
|
||||
{
|
||||
required: false,
|
||||
name: :alert_events,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Enable notifications for alert_events'
|
||||
},
|
||||
{
|
||||
required: false,
|
||||
name: :confidential_issues_events,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Enable notifications for confidential_issues_events'
|
||||
},
|
||||
{
|
||||
required: false,
|
||||
name: :merge_requests_events,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Enable notifications for merge_requests_events'
|
||||
},
|
||||
{
|
||||
required: false,
|
||||
name: :note_events,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Enable notifications for note_events'
|
||||
},
|
||||
{
|
||||
required: false,
|
||||
name: :confidential_note_events,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Enable notifications for confidential_note_events'
|
||||
},
|
||||
{
|
||||
required: false,
|
||||
name: :tag_push_events,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Enable notifications for tag_push_events'
|
||||
},
|
||||
{
|
||||
required: false,
|
||||
name: :deployment_events,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Enable notifications for deployment_events'
|
||||
},
|
||||
{
|
||||
required: false,
|
||||
name: :job_events,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Enable notifications for job_events'
|
||||
},
|
||||
{
|
||||
required: false,
|
||||
name: :pipeline_events,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Enable notifications for pipeline_events'
|
||||
},
|
||||
{
|
||||
required: false,
|
||||
name: :wiki_page_events,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Enable notifications for wiki_page_events'
|
||||
}
|
||||
].freeze
|
||||
|
|
@ -243,7 +243,7 @@ module API
|
|||
{
|
||||
required: false,
|
||||
name: :app_store_protected_refs,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Only enable for protected refs'
|
||||
}
|
||||
],
|
||||
|
|
@ -285,7 +285,7 @@ module API
|
|||
{
|
||||
required: false,
|
||||
name: :enable_ssl_verification,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Enable SSL verification'
|
||||
},
|
||||
{
|
||||
|
|
@ -343,7 +343,7 @@ module API
|
|||
{
|
||||
required: false,
|
||||
name: :enable_ssl_verification,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'DEPRECATED: This parameter has no effect since SSL verification will always be enabled'
|
||||
}
|
||||
],
|
||||
|
|
@ -417,7 +417,7 @@ module API
|
|||
{
|
||||
required: false,
|
||||
name: :archive_trace_events,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'When enabled, job logs will be collected by Datadog and shown along pipeline execution traces'
|
||||
},
|
||||
{
|
||||
|
|
@ -471,7 +471,7 @@ module API
|
|||
{
|
||||
required: false,
|
||||
name: :enable_ssl_verification,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Enable SSL verification'
|
||||
}
|
||||
],
|
||||
|
|
@ -485,13 +485,13 @@ module API
|
|||
{
|
||||
required: false,
|
||||
name: :disable_diffs,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Disable code diffs'
|
||||
},
|
||||
{
|
||||
required: false,
|
||||
name: :send_from_committer_email,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Send from committer'
|
||||
},
|
||||
{
|
||||
|
|
@ -598,7 +598,7 @@ module API
|
|||
{
|
||||
required: false,
|
||||
name: :colorize_messages,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Colorize messages'
|
||||
}
|
||||
],
|
||||
|
|
@ -612,7 +612,7 @@ module API
|
|||
{
|
||||
required: false,
|
||||
name: :enable_ssl_verification,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Enable SSL verification'
|
||||
},
|
||||
{
|
||||
|
|
@ -668,7 +668,7 @@ module API
|
|||
{
|
||||
required: false,
|
||||
name: :jira_issue_transition_automatic,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Enable automatic issue transitions'
|
||||
},
|
||||
{
|
||||
|
|
@ -692,7 +692,7 @@ module API
|
|||
{
|
||||
required: false,
|
||||
name: :comment_on_event_enabled,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Enable comments inside Jira issues on each GitLab event (commit / merge request)'
|
||||
}
|
||||
],
|
||||
|
|
@ -750,13 +750,13 @@ module API
|
|||
{
|
||||
required: false,
|
||||
name: :notify_only_broken_pipelines,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Notify only broken pipelines'
|
||||
},
|
||||
{
|
||||
required: false,
|
||||
name: :notify_only_default_branch,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Send notifications only for the default branch'
|
||||
},
|
||||
{
|
||||
|
|
@ -946,7 +946,7 @@ module API
|
|||
{
|
||||
required: false,
|
||||
name: :enable_ssl_verification,
|
||||
type: Boolean,
|
||||
type: ::Grape::API::Boolean,
|
||||
desc: 'Enable SSL verification'
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -78,18 +78,6 @@ module Gitlab
|
|||
rescue URI::InvalidURIError, KeyError
|
||||
end
|
||||
|
||||
def metrics_dashboard_url
|
||||
return unless environment && full_query && title
|
||||
|
||||
metrics_dashboard_project_environment_url(
|
||||
project,
|
||||
environment,
|
||||
embed_json: dashboard_json,
|
||||
embedded: true,
|
||||
**alert_embed_window_params
|
||||
)
|
||||
end
|
||||
|
||||
def has_required_attributes?
|
||||
project && title && starts_at_raw
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,59 +7,14 @@ module Gitlab
|
|||
class ClusterEndpointInserter < BaseStage
|
||||
def transform!
|
||||
verify_params
|
||||
|
||||
for_metrics do |metric|
|
||||
metric[:prometheus_endpoint_path] = endpoint_for_metric(metric)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def admin_url(metric)
|
||||
Gitlab::Routing.url_helpers.prometheus_api_admin_cluster_path(
|
||||
params[:cluster],
|
||||
proxy_path: query_type(metric),
|
||||
query: query_for_metric(metric)
|
||||
)
|
||||
end
|
||||
|
||||
def endpoint_for_metric(metric)
|
||||
case params[:cluster_type]
|
||||
when :admin
|
||||
admin_url(metric)
|
||||
when :group
|
||||
error!(_('Group is required when cluster_type is :group')) unless params[:group]
|
||||
group_url(metric)
|
||||
when :project
|
||||
error!(_('Project is required when cluster_type is :project')) unless project
|
||||
project_url(metric)
|
||||
else
|
||||
error!(_('Unrecognized cluster type'))
|
||||
end
|
||||
end
|
||||
|
||||
def error!(message)
|
||||
raise Errors::DashboardProcessingError, message
|
||||
end
|
||||
|
||||
def group_url(metric)
|
||||
Gitlab::Routing.url_helpers.prometheus_api_group_cluster_path(
|
||||
params[:group],
|
||||
params[:cluster],
|
||||
proxy_path: query_type(metric),
|
||||
query: query_for_metric(metric)
|
||||
)
|
||||
end
|
||||
|
||||
def project_url(metric)
|
||||
Gitlab::Routing.url_helpers.prometheus_api_project_cluster_path(
|
||||
project,
|
||||
params[:cluster],
|
||||
proxy_path: query_type(metric),
|
||||
query: query_for_metric(metric)
|
||||
)
|
||||
end
|
||||
|
||||
def query_type(metric)
|
||||
metric[:query] ? :query : :query_range
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,26 +12,6 @@ module Gitlab
|
|||
ANCHOR_PATTERN = '(?<anchor>\#[a-z0-9_-]+)?'
|
||||
DASH_PATTERN = '(?:/-)'
|
||||
|
||||
# Matches urls for a metrics dashboard.
|
||||
# This regex needs to match the old metrics URL, the new metrics URL,
|
||||
# and the dashboard URL (inline_metrics_redactor_filter.rb
|
||||
# uses this regex to match against the dashboard URL.)
|
||||
#
|
||||
# EX - Old URL: https://<host>/<namespace>/<project>/environments/<env_id>/metrics
|
||||
# OR
|
||||
# New URL: https://<host>/<namespace>/<project>/-/metrics?environment=<env_id>
|
||||
# OR
|
||||
# dashboard URL: https://<host>/<namespace>/<project>/environments/<env_id>/metrics_dashboard
|
||||
def metrics_regex
|
||||
strong_memoize(:metrics_regex) do
|
||||
regex_for_project_metrics(
|
||||
%r{
|
||||
( #{environment_metrics_regex} ) | ( #{non_environment_metrics_regex} )
|
||||
}x
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# Matches dashboard urls for a Grafana embed.
|
||||
#
|
||||
# EX - https://<host>/<namespace>/<project>/grafana/metrics_dashboard
|
||||
|
|
@ -99,11 +79,6 @@ module Gitlab
|
|||
.symbolize_keys
|
||||
end
|
||||
|
||||
# Builds a metrics dashboard url based on the passed in arguments
|
||||
def build_dashboard_url(...)
|
||||
Gitlab::Routing.url_helpers.metrics_dashboard_namespace_project_environment_url(...)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def environment_metrics_regex
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ module Gitlab
|
|||
}.freeze
|
||||
|
||||
UUID_V5_PATTERN = /\h{8}-\h{4}-5\h{3}-\h{4}-\h{12}/.freeze
|
||||
NAMESPACE_REGEX = /(\h{8})-(\h{4})-(\h{4})-(\h{4})-(\h{4})(\h{8})/.freeze
|
||||
PACK_PATTERN = "NnnnnN"
|
||||
|
||||
class << self
|
||||
def v5(name, namespace_id: default_namespace_id)
|
||||
|
|
@ -25,12 +23,7 @@ module Gitlab
|
|||
private
|
||||
|
||||
def default_namespace_id
|
||||
@default_namespace_id ||= begin
|
||||
namespace_uuid = NAMESPACE_IDS.fetch(Rails.env.to_sym)
|
||||
# Digest::UUID is broken when using a UUID as a namespace_id
|
||||
# https://github.com/rails/rails/issues/37681#issue-520718028
|
||||
namespace_uuid.scan(NAMESPACE_REGEX).flatten.map { |s| s.to_i(16) }.pack(PACK_PATTERN)
|
||||
end
|
||||
NAMESPACE_IDS.fetch(Rails.env.to_sym)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -99,6 +99,16 @@ msgid_plural "%d Approvals"
|
|||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "%d Issue"
|
||||
msgid_plural "%d Issues"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "%d Merge Request"
|
||||
msgid_plural "%d Merge Requests"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "%d Module"
|
||||
msgid_plural "%d Modules"
|
||||
msgstr[0] ""
|
||||
|
|
@ -354,16 +364,6 @@ msgid_plural "%d more comments"
|
|||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "%d opened Issue"
|
||||
msgid_plural "%d opened Issues"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "%d opened Merge Request"
|
||||
msgid_plural "%d opened Merge Requests"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "%d package"
|
||||
msgid_plural "%d packages"
|
||||
msgstr[0] ""
|
||||
|
|
@ -3867,9 +3867,6 @@ msgstr ""
|
|||
msgid "AdminUsers|Is using seat"
|
||||
msgstr ""
|
||||
|
||||
msgid "AdminUsers|Issues and merge requests authored by this user are hidden from other users."
|
||||
msgstr ""
|
||||
|
||||
msgid "AdminUsers|It's you!"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -3915,6 +3912,9 @@ msgstr ""
|
|||
msgid "AdminUsers|Private profile"
|
||||
msgstr ""
|
||||
|
||||
msgid "AdminUsers|Projects, issues, merge requests, and comments of this user are hidden from other users."
|
||||
msgstr ""
|
||||
|
||||
msgid "AdminUsers|Reactivating a user will:"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -21478,9 +21478,6 @@ msgstr ""
|
|||
msgid "Group information"
|
||||
msgstr ""
|
||||
|
||||
msgid "Group is required when cluster_type is :group"
|
||||
msgstr ""
|
||||
|
||||
msgid "Group jobs by"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -35653,9 +35650,6 @@ msgstr ""
|
|||
msgid "Project information"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project is required when cluster_type is :project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project members"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -42002,6 +41996,9 @@ msgstr ""
|
|||
msgid "SecurityReports|There was an error adding the comment."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityReports|There was an error creating a Jira issue for the finding. Please try again."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityReports|There was an error creating the issue."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -48937,9 +48934,6 @@ msgstr ""
|
|||
msgid "Unrecognized approval status."
|
||||
msgstr ""
|
||||
|
||||
msgid "Unrecognized cluster type"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unresolve"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -50193,7 +50187,7 @@ msgstr ""
|
|||
msgid "ValueStreamAnalytics|High vulnerabilities over time."
|
||||
msgstr ""
|
||||
|
||||
msgid "ValueStreamAnalytics|Key metrics"
|
||||
msgid "ValueStreamAnalytics|Lifecycle metrics"
|
||||
msgstr ""
|
||||
|
||||
msgid "ValueStreamAnalytics|Median time an incident was open on a production environment in the given time period."
|
||||
|
|
@ -50506,9 +50500,6 @@ msgstr ""
|
|||
msgid "View page @ "
|
||||
msgstr ""
|
||||
|
||||
msgid "View performance dashboard."
|
||||
msgstr ""
|
||||
|
||||
msgid "View project in admin area"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -50538,9 +50529,6 @@ msgstr ""
|
|||
msgid "View the latest successful deployment to this environment"
|
||||
msgstr ""
|
||||
|
||||
msgid "View the performance dashboard at"
|
||||
msgstr ""
|
||||
|
||||
msgid "View usage details"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ module RuboCop
|
|||
# with offenses.
|
||||
#
|
||||
# See https://gitlab.com/gitlab-org/gitlab/-/issues/415330#caveats
|
||||
# on why the entry must end with `.html.haml.rb`.
|
||||
RETAIN_EXCLUSIONS = %r{\.html\.haml\.rb$}
|
||||
# on why the entry must end with `.haml.rb`.
|
||||
RETAIN_EXCLUSIONS = %r{\.haml\.rb$}
|
||||
|
||||
class << self
|
||||
attr_accessor :base_directory
|
||||
|
|
|
|||
|
|
@ -113,18 +113,6 @@ RSpec.describe Projects::ClustersController, feature_category: :deployment_manag
|
|||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'GET #metrics_dashboard for dashboard', 'Cluster health' do
|
||||
let(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) }
|
||||
|
||||
let(:metrics_dashboard_req_params) do
|
||||
{
|
||||
id: cluster.id,
|
||||
namespace_id: project.namespace.full_path,
|
||||
project_id: project.path
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST create for existing cluster' do
|
||||
let(:params) do
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,4 +6,8 @@ FactoryBot.define do
|
|||
project
|
||||
access_level { Gitlab::Access::REPORTER }
|
||||
end
|
||||
|
||||
trait :owner do
|
||||
access_level { Gitlab::Access::OWNER }
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe ProjectsFinder do
|
||||
RSpec.describe ProjectsFinder, feature_category: :groups_and_projects do
|
||||
include AdminModeHelper
|
||||
|
||||
describe '#execute' do
|
||||
|
|
@ -25,6 +25,12 @@ RSpec.describe ProjectsFinder do
|
|||
create(:project, :private, name: 'D', path: 'D')
|
||||
end
|
||||
|
||||
let_it_be(:banned_user_project) do
|
||||
create(:project, :public, name: 'Project created by a banned user', creator: create(:user, :banned)).tap do |p|
|
||||
create(:project_authorization, :owner, user: p.creator, project: p)
|
||||
end
|
||||
end
|
||||
|
||||
let(:params) { {} }
|
||||
let(:current_user) { user }
|
||||
let(:project_ids_relation) { nil }
|
||||
|
|
@ -488,16 +494,32 @@ RSpec.describe ProjectsFinder do
|
|||
describe 'with admin user' do
|
||||
let(:user) { create(:admin) }
|
||||
|
||||
context 'admin mode enabled' do
|
||||
context 'with admin mode enabled' do
|
||||
before do
|
||||
enable_admin_mode!(current_user)
|
||||
end
|
||||
|
||||
it { is_expected.to match_array([public_project, internal_project, private_project, shared_project]) }
|
||||
it do
|
||||
is_expected.to match_array([
|
||||
public_project,
|
||||
internal_project,
|
||||
private_project,
|
||||
shared_project,
|
||||
banned_user_project
|
||||
])
|
||||
end
|
||||
end
|
||||
|
||||
context 'admin mode disabled' do
|
||||
context 'with admin mode disabled' do
|
||||
it { is_expected.to match_array([public_project, internal_project]) }
|
||||
|
||||
context 'when hide_projects_of_banned_users FF is disabled' do
|
||||
before do
|
||||
stub_feature_flags(hide_projects_of_banned_users: false)
|
||||
end
|
||||
|
||||
it { is_expected.to match_array([public_project, internal_project, banned_user_project]) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,23 +2,57 @@
|
|||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"label",
|
||||
"prometheus_endpoint_path"
|
||||
"label"
|
||||
],
|
||||
"oneOf": [
|
||||
{ "required": ["query"] },
|
||||
{ "required": ["query_range"] }
|
||||
{
|
||||
"required": [
|
||||
"query"
|
||||
]
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"query_range"
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"id": { "type": "string" },
|
||||
"query_range": { "type": ["string", "number"] },
|
||||
"query": { "type": ["string", "number"] },
|
||||
"unit": { "type": "string" },
|
||||
"label": { "type": "string" },
|
||||
"track": { "type": "string" },
|
||||
"prometheus_endpoint_path": { "type": "string" },
|
||||
"metric_id": { "type": "number" },
|
||||
"edit_path": { "type": ["string", "null"] }
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"query_range": {
|
||||
"type": [
|
||||
"string",
|
||||
"number"
|
||||
]
|
||||
},
|
||||
"query": {
|
||||
"type": [
|
||||
"string",
|
||||
"number"
|
||||
]
|
||||
},
|
||||
"unit": {
|
||||
"type": "string"
|
||||
},
|
||||
"label": {
|
||||
"type": "string"
|
||||
},
|
||||
"track": {
|
||||
"type": "string"
|
||||
},
|
||||
"prometheus_endpoint_path": {
|
||||
"type": "string"
|
||||
},
|
||||
"metric_id": {
|
||||
"type": "number"
|
||||
},
|
||||
"edit_path": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { GlDropdownItem, GlAvatarLabeled, GlLoadingIcon } from '@gitlab/ui';
|
||||
import { GlAvatarLabeled, GlLoadingIcon } from '@gitlab/ui';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
||||
import SuggestionsDropdown from '~/content_editor/components/suggestions_dropdown.vue';
|
||||
|
|
@ -113,7 +113,7 @@ describe('~/content_editor/components/suggestions_dropdown', () => {
|
|||
${'emoji'} | ${'emoji'} | ${':'} | ${exampleEmoji} | ${`😃`} | ${insertedEmojiProps}
|
||||
`(
|
||||
'runs a command to insert the selected $referenceType',
|
||||
({ char, nodeType, referenceType, reference, insertedText, insertedProps }) => {
|
||||
async ({ char, nodeType, referenceType, reference, insertedText, insertedProps }) => {
|
||||
const commandSpy = jest.fn();
|
||||
|
||||
buildWrapper({
|
||||
|
|
@ -129,7 +129,10 @@ describe('~/content_editor/components/suggestions_dropdown', () => {
|
|||
},
|
||||
});
|
||||
|
||||
wrapper.findComponent(GlDropdownItem).vm.$emit('click');
|
||||
await wrapper
|
||||
.findByTestId('content-editor-suggestions-dropdown')
|
||||
.find('li .gl-new-dropdown-item-content')
|
||||
.trigger('click');
|
||||
|
||||
expect(commandSpy).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@ exports[`Dashboard template matches the default snapshot 1`] = `
|
|||
class="prometheus-graphs"
|
||||
data-testid="prometheus-graphs"
|
||||
environmentstate="available"
|
||||
metricsdashboardbasepath="/monitoring/monitor-project/-/metrics?environment=1"
|
||||
metricsendpoint="/monitoring/monitor-project/-/environments/1/additional_metrics.json"
|
||||
>
|
||||
<div>
|
||||
<gl-alert-stub
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import GROUP_IMPORT_SVG_URL from '@gitlab/svgs/dist/illustrations/group-import.svg?url';
|
||||
import GROUP_NEW_SVG_URL from '@gitlab/svgs/dist/illustrations/group-new.svg?url';
|
||||
|
||||
import App from '~/pages/groups/new/components/app.vue';
|
||||
import NewNamespacePage from '~/vue_shared/new_namespace/new_namespace_page.vue';
|
||||
|
||||
|
|
@ -27,6 +30,7 @@ describe('App component', () => {
|
|||
{ href: '#', text: 'New group' },
|
||||
]);
|
||||
expect(findCreateGroupPanel().title).toBe('Create group');
|
||||
expect(findCreateGroupPanel().imageSrc).toBe(GROUP_NEW_SVG_URL);
|
||||
});
|
||||
|
||||
it('creates correct component for subgroup creation', () => {
|
||||
|
|
@ -45,5 +49,6 @@ describe('App component', () => {
|
|||
]);
|
||||
expect(findCreateGroupPanel().title).toBe('Create subgroup');
|
||||
expect(findCreateGroupPanel().detailProps).toEqual(detailProps);
|
||||
expect(findCreateGroupPanel().imageSrc).toBe(GROUP_IMPORT_SVG_URL);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Experimental new project creation app creates correct panels 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"description": "Create a blank project to store your files, plan your work, and collaborate on code, among other things.",
|
||||
"imageSrc": "file-mock",
|
||||
"key": "blank",
|
||||
"name": "blank_project",
|
||||
"selector": "#blank-project-pane",
|
||||
"title": "Create blank project",
|
||||
},
|
||||
Object {
|
||||
"description": "Create a project pre-populated with the necessary files to get you started quickly.",
|
||||
"imageSrc": "file-mock",
|
||||
"key": "template",
|
||||
"name": "create_from_template",
|
||||
"selector": "#create-from-template-pane",
|
||||
"title": "Create from template",
|
||||
},
|
||||
Object {
|
||||
"description": "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab.",
|
||||
"imageSrc": "file-mock",
|
||||
"key": "import",
|
||||
"name": "import_project",
|
||||
"selector": "#import-project-pane",
|
||||
"title": "Import project",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
|
@ -23,6 +23,12 @@ describe('Experimental new project creation app', () => {
|
|||
expect(wrapper.find(guidelineSelector).text()).toBe(DEMO_GUIDELINES);
|
||||
});
|
||||
|
||||
it('creates correct panels', () => {
|
||||
createComponent();
|
||||
|
||||
expect(findNewNamespacePage().props('panels')).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it.each`
|
||||
isCiCdAvailable | outcome
|
||||
${false} | ${'do not show CI/CD panel'}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,18 @@ describe('Welcome page', () => {
|
|||
expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_tab', { label: 'test' });
|
||||
});
|
||||
|
||||
it('renders image', () => {
|
||||
const mockImgSrc = 'image1.svg';
|
||||
|
||||
createComponent({
|
||||
propsData: {
|
||||
panels: [{ name: 'test', href: '#', imageSrc: mockImgSrc }],
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.find('img').attributes('src')).toBe(mockImgSrc);
|
||||
});
|
||||
|
||||
it('renders footer slot if provided', () => {
|
||||
const DUMMY = 'Test message';
|
||||
createComponent({
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ describe('Experimental new namespace creation app', () => {
|
|||
const findWelcomePage = () => wrapper.findComponent(WelcomePage);
|
||||
const findLegacyContainer = () => wrapper.findComponent(LegacyContainer);
|
||||
const findBreadcrumb = () => wrapper.findComponent(GlBreadcrumb);
|
||||
const findImage = () => wrapper.find('img');
|
||||
const findNewTopLevelGroupAlert = () => wrapper.findComponent(NewTopLevelGroupAlert);
|
||||
const findSuperSidebarToggle = () => wrapper.findComponent(SuperSidebarToggle);
|
||||
|
||||
|
|
@ -22,8 +23,8 @@ describe('Experimental new namespace creation app', () => {
|
|||
title: 'Create something',
|
||||
initialBreadcrumbs: [{ text: 'Something', href: '#' }],
|
||||
panels: [
|
||||
{ name: 'panel1', selector: '#some-selector1' },
|
||||
{ name: 'panel2', selector: '#some-selector2' },
|
||||
{ name: 'panel1', selector: '#some-selector1', imageSrc: 'panel1.svg' },
|
||||
{ name: 'panel2', selector: '#some-selector2', imageSrc: 'panel2.svg' },
|
||||
],
|
||||
persistenceKey: 'DEMO-PERSISTENCE-KEY',
|
||||
};
|
||||
|
|
@ -82,6 +83,10 @@ describe('Experimental new namespace creation app', () => {
|
|||
expect(breadcrumb.exists()).toBe(true);
|
||||
expect(breadcrumb.props().items[0].text).toBe(DEFAULT_PROPS.initialBreadcrumbs[0].text);
|
||||
});
|
||||
|
||||
it('renders images', () => {
|
||||
expect(findImage().attributes('src')).toBe(DEFAULT_PROPS.panels[1].imageSrc);
|
||||
});
|
||||
});
|
||||
|
||||
it('renders extra description if provided', () => {
|
||||
|
|
|
|||
|
|
@ -137,7 +137,8 @@ RSpec.describe Resolvers::Users::ParticipantsResolver do
|
|||
|
||||
# 1 extra query per source (3 emojis + 2 notes) to fetch participables collection
|
||||
# 2 extra queries to load work item widgets collection
|
||||
expect { query.call }.not_to exceed_query_limit(control_count).with_threshold(7)
|
||||
# 1 extra query to load the project creator to check if they are banned
|
||||
expect { query.call }.not_to exceed_query_limit(control_count).with_threshold(8)
|
||||
end
|
||||
|
||||
it 'does not execute N+1 for system note metadata relation' do
|
||||
|
|
|
|||
|
|
@ -68,17 +68,5 @@ RSpec.describe EnvironmentHelper, feature_category: :environment_management do
|
|||
graphql_etag_key: environment.etag_cache_key
|
||||
}.to_json)
|
||||
end
|
||||
|
||||
context 'when metrics dashboard feature is available' do
|
||||
before do
|
||||
stub_feature_flags(remove_monitor_metrics: false)
|
||||
end
|
||||
|
||||
it 'includes metrics path' do
|
||||
expect(Gitlab::Json.parse(subject)).to include(
|
||||
'environment_metrics_path' => project_metrics_dashboard_path(project, environment: environment)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ RSpec.describe EnvironmentsHelper, feature_category: :environment_management do
|
|||
expect(metrics_data).to include(
|
||||
'settings_path' => edit_project_settings_integration_path(project, 'prometheus'),
|
||||
'clusters_path' => project_clusters_path(project),
|
||||
'metrics_dashboard_base_path' => project_metrics_dashboard_path(project, environment: environment),
|
||||
'current_environment_name' => environment.name,
|
||||
'documentation_path' => help_page_path('administration/monitoring/prometheus/index.md'),
|
||||
'add_dashboard_documentation_path' => help_page_path('operations/metrics/dashboards/index.md', anchor: 'add-a-new-dashboard-to-your-project'),
|
||||
|
|
@ -30,7 +29,6 @@ RSpec.describe EnvironmentsHelper, feature_category: :environment_management do
|
|||
'empty_loading_svg_path' => match_asset_path('/assets/illustrations/monitoring/loading.svg'),
|
||||
'empty_no_data_svg_path' => match_asset_path('/assets/illustrations/monitoring/no_data.svg'),
|
||||
'empty_unable_to_connect_svg_path' => match_asset_path('/assets/illustrations/monitoring/unable_to_connect.svg'),
|
||||
'metrics_endpoint' => additional_metrics_project_environment_path(project, environment, format: :json),
|
||||
'deployments_endpoint' => project_environment_deployments_path(project, environment, format: :json),
|
||||
'default_branch' => 'master',
|
||||
'project_path' => project_path(project),
|
||||
|
|
@ -82,30 +80,6 @@ RSpec.describe EnvironmentsHelper, feature_category: :environment_management do
|
|||
it { is_expected.to include('environment_state' => 'stopped') }
|
||||
end
|
||||
|
||||
context 'when request is from project scoped metrics path' do
|
||||
let(:request) { double('request', path: path) }
|
||||
|
||||
before do
|
||||
allow(helper).to receive(:request).and_return(request)
|
||||
end
|
||||
|
||||
context '/:namespace/:project/-/metrics' do
|
||||
let(:path) { project_metrics_dashboard_path(project) }
|
||||
|
||||
it 'uses correct path for metrics_dashboard_base_path' do
|
||||
expect(metrics_data['metrics_dashboard_base_path']).to eq(project_metrics_dashboard_path(project))
|
||||
end
|
||||
end
|
||||
|
||||
context '/:namespace/:project/-/metrics/some_custom_dashboard.yml' do
|
||||
let(:path) { "#{project_metrics_dashboard_path(project)}/some_custom_dashboard.yml" }
|
||||
|
||||
it 'uses correct path for metrics_dashboard_base_path' do
|
||||
expect(metrics_data['metrics_dashboard_base_path']).to eq(project_metrics_dashboard_path(project))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when metrics dashboard feature is unavailable' do
|
||||
before do
|
||||
stub_feature_flags(remove_monitor_metrics: true)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
|
|||
let_it_be(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
helper.instance_variable_set(:@project, project)
|
||||
end
|
||||
|
||||
|
|
@ -143,7 +144,6 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
|
|||
let(:project) { project_with_repo }
|
||||
|
||||
before do
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
allow(helper).to receive(:can?).with(user, :read_cross_project) { true }
|
||||
allow(user).to receive(:max_member_access_for_project).and_return(40)
|
||||
allow(Gitlab::I18n).to receive(:locale).and_return('es')
|
||||
|
|
@ -287,10 +287,6 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
|
|||
end
|
||||
|
||||
describe '#show_no_ssh_key_message?' do
|
||||
before do
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
end
|
||||
|
||||
context 'user has no keys' do
|
||||
it 'returns true' do
|
||||
expect(helper.show_no_ssh_key_message?).to be_truthy
|
||||
|
|
@ -307,10 +303,6 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
|
|||
end
|
||||
|
||||
describe '#show_no_password_message?' do
|
||||
before do
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
end
|
||||
|
||||
context 'user has password set' do
|
||||
it 'returns false' do
|
||||
expect(helper.show_no_password_message?).to be_falsey
|
||||
|
|
@ -346,10 +338,6 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
|
|||
describe '#no_password_message' do
|
||||
let(:user) { create(:user, password_automatically_set: true) }
|
||||
|
||||
before do
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
end
|
||||
|
||||
context 'password authentication is enabled for Git' do
|
||||
it 'returns message prompting user to set password or set up a PAT' do
|
||||
stub_application_setting(password_authentication_enabled_for_git?: true)
|
||||
|
|
@ -431,10 +419,10 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
|
|||
end
|
||||
|
||||
describe 'default_clone_protocol' do
|
||||
let(:user) { nil }
|
||||
|
||||
context 'when user is not logged in and gitlab protocol is HTTP' do
|
||||
it 'returns HTTP' do
|
||||
allow(helper).to receive(:current_user).and_return(nil)
|
||||
|
||||
expect(helper.send(:default_clone_protocol)).to eq('http')
|
||||
end
|
||||
end
|
||||
|
|
@ -442,7 +430,6 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
|
|||
context 'when user is not logged in and gitlab protocol is HTTPS' do
|
||||
it 'returns HTTPS' do
|
||||
stub_config_setting(protocol: 'https')
|
||||
allow(helper).to receive(:current_user).and_return(nil)
|
||||
|
||||
expect(helper.send(:default_clone_protocol)).to eq('https')
|
||||
end
|
||||
|
|
@ -453,10 +440,6 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
|
|||
let(:user) { double(:user, fork_of: nil) }
|
||||
let(:project) { double(:project, id: 1) }
|
||||
|
||||
before do
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
end
|
||||
|
||||
context 'when there is no current_user' do
|
||||
let(:user) { nil }
|
||||
|
||||
|
|
@ -543,10 +526,6 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
|
|||
describe '#git_user_name' do
|
||||
let(:user) { build_stubbed(:user, name: 'John "A" Doe53') }
|
||||
|
||||
before do
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
end
|
||||
|
||||
it 'parses quotes in name' do
|
||||
expect(helper.send(:git_user_name)).to eq('John \"A\" Doe53')
|
||||
end
|
||||
|
|
@ -554,9 +533,7 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
|
|||
|
||||
describe '#git_user_email' do
|
||||
context 'not logged-in' do
|
||||
before do
|
||||
allow(helper).to receive(:current_user).and_return(nil)
|
||||
end
|
||||
let(:user) { nil }
|
||||
|
||||
it 'returns your@email.com' do
|
||||
expect(helper.send(:git_user_email)).to eq('your@email.com')
|
||||
|
|
@ -564,10 +541,6 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
|
|||
end
|
||||
|
||||
context 'user logged in' do
|
||||
before do
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
end
|
||||
|
||||
context 'user has no configured commit email' do
|
||||
it 'returns the primary email' do
|
||||
expect(helper.send(:git_user_email)).to eq(user.email)
|
||||
|
|
@ -807,9 +780,7 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
|
|||
|
||||
describe '#can_admin_project_member?' do
|
||||
context 'when user is project owner' do
|
||||
before do
|
||||
allow(helper).to receive(:current_user) { project.owner }
|
||||
end
|
||||
let(:user) { project.owner }
|
||||
|
||||
it 'returns true for owner of project' do
|
||||
expect(helper.can_admin_project_member?(project)).to eq true
|
||||
|
|
@ -829,7 +800,6 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
|
|||
with_them do
|
||||
before do
|
||||
project.add_role(user, user_project_role)
|
||||
allow(helper).to receive(:current_user) { user }
|
||||
end
|
||||
|
||||
it 'resolves if the user can import members' do
|
||||
|
|
@ -1016,7 +986,6 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
|
|||
|
||||
before do
|
||||
allow(helper).to receive(:can?) { true }
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
end
|
||||
|
||||
it 'includes project_permissions_settings' do
|
||||
|
|
@ -1188,10 +1157,6 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
|
|||
end
|
||||
|
||||
shared_examples 'configure import method modal' do
|
||||
before do
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
end
|
||||
|
||||
context 'as a user' do
|
||||
it 'returns a link to contact an administrator' do
|
||||
allow(user).to receive(:can_admin_all_resources?).and_return(false)
|
||||
|
|
@ -1290,16 +1255,14 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
|
|||
end
|
||||
|
||||
describe '#can_admin_associated_clusters?' do
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
let_it_be_with_reload(:project) { create(:project) }
|
||||
|
||||
subject { helper.send(:can_admin_associated_clusters?, project) }
|
||||
|
||||
before do
|
||||
allow(helper).to receive(:current_user).and_return(current_user)
|
||||
allow(helper)
|
||||
.to receive(:can?)
|
||||
.with(current_user, :admin_cluster, namespace)
|
||||
.with(user, :admin_cluster, namespace)
|
||||
.and_return(user_can_admin_cluster)
|
||||
end
|
||||
|
||||
|
|
@ -1477,8 +1440,6 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
|
|||
end
|
||||
|
||||
it 'returns the data related to fork divergence' do
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
|
||||
ahead_path =
|
||||
"/#{project.full_path}/-/compare/#{source_project.default_branch}...ref?from_project_id=#{source_project.id}"
|
||||
behind_path =
|
||||
|
|
@ -1500,8 +1461,6 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
|
|||
end
|
||||
|
||||
it 'returns view_mr_path if a merge request for the branch exists' do
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
|
||||
merge_request =
|
||||
create(:merge_request, source_project: project, target_project: project_with_repo,
|
||||
source_branch: project.default_branch, target_branch: project_with_repo.default_branch)
|
||||
|
|
@ -1523,8 +1482,6 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
|
|||
|
||||
with_them do
|
||||
it 'create_mr_path is nil' do
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
|
||||
project.add_member(user, project_role)
|
||||
source_project.add_member(user, source_project_role)
|
||||
|
||||
|
|
@ -1562,4 +1519,50 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
|
|||
|
||||
it { expect(subject).to eq('ssh_url_to_repo') }
|
||||
end
|
||||
|
||||
describe '#can_view_branch_rules?' do
|
||||
subject { helper.can_view_branch_rules? }
|
||||
|
||||
context 'when user is a maintainer' do
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
end
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
|
||||
context 'when user is a developer' do
|
||||
before do
|
||||
project.add_developer(user)
|
||||
end
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#can_push_code?' do
|
||||
subject { helper.can_push_code? }
|
||||
|
||||
context 'when user is nil' do
|
||||
let(:user) { nil }
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
|
||||
context 'when user is a developer on the project' do
|
||||
before do
|
||||
project.add_developer(user)
|
||||
end
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
|
||||
context 'when user is a reporter on the project' do
|
||||
before do
|
||||
project.add_reporter(user)
|
||||
end
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -185,8 +185,6 @@ RSpec.describe Gitlab::AlertManagement::Payload::Prometheus do
|
|||
|
||||
subject { parsed_payload.metrics_dashboard_url }
|
||||
|
||||
it { is_expected.to eq(dashboard_url_for_alert) }
|
||||
|
||||
context 'without environment' do
|
||||
let(:raw_payload) { payload.except('labels') }
|
||||
|
||||
|
|
|
|||
|
|
@ -5,78 +5,6 @@ require 'spec_helper'
|
|||
RSpec.describe Gitlab::Metrics::Dashboard::Url do
|
||||
include Gitlab::Routing.url_helpers
|
||||
|
||||
describe '#metrics_regex' do
|
||||
let(:environment_id) { 1 }
|
||||
let(:url_params) do
|
||||
[
|
||||
'foo',
|
||||
'bar',
|
||||
environment_id,
|
||||
{
|
||||
start: '2019-08-02T05:43:09.000Z',
|
||||
dashboard: 'config/prometheus/common_metrics.yml',
|
||||
group: 'awesome group',
|
||||
anchor: 'title'
|
||||
}
|
||||
]
|
||||
end
|
||||
|
||||
let(:expected_params) do
|
||||
{
|
||||
'url' => url,
|
||||
'namespace' => 'foo',
|
||||
'project' => 'bar',
|
||||
'environment' => '1',
|
||||
'query' => '?dashboard=config%2Fprometheus%2Fcommon_metrics.yml&group=awesome+group&start=2019-08-02T05%3A43%3A09.000Z',
|
||||
'anchor' => '#title'
|
||||
}
|
||||
end
|
||||
|
||||
subject { described_class.metrics_regex }
|
||||
|
||||
context 'for /-/environments/:environment_id/metrics route' do
|
||||
let(:url) { metrics_namespace_project_environment_url(*url_params) }
|
||||
|
||||
it_behaves_like 'regex which matches url when expected'
|
||||
end
|
||||
|
||||
context 'for /-/metrics?environment=:environment_id route' do
|
||||
let(:url) { namespace_project_metrics_dashboard_url(*url_params) }
|
||||
let(:url_params) do
|
||||
[
|
||||
'namespace1',
|
||||
'project1',
|
||||
{
|
||||
environment: environment_id,
|
||||
start: '2019-08-02T05:43:09.000Z',
|
||||
dashboard: 'config/prometheus/common_metrics.yml',
|
||||
group: 'awesome group',
|
||||
anchor: 'title'
|
||||
}
|
||||
]
|
||||
end
|
||||
|
||||
let(:expected_params) do
|
||||
{
|
||||
'url' => url,
|
||||
'namespace' => 'namespace1',
|
||||
'project' => 'project1',
|
||||
'environment' => environment_id.to_s,
|
||||
'query' => "?dashboard=config%2Fprometheus%2Fcommon_metrics.yml&environment=#{environment_id}&group=awesome+group&start=2019-08-02T05%3A43%3A09.000Z",
|
||||
'anchor' => '#title'
|
||||
}
|
||||
end
|
||||
|
||||
it_behaves_like 'regex which matches url when expected'
|
||||
end
|
||||
|
||||
context 'for metrics_dashboard route' do
|
||||
let(:url) { metrics_dashboard_namespace_project_environment_url(*url_params) }
|
||||
|
||||
it_behaves_like 'regex which matches url when expected'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#clusters_regex' do
|
||||
let(:url) { Gitlab::Routing.url_helpers.namespace_project_cluster_url(*url_params) }
|
||||
let(:url_params) do
|
||||
|
|
@ -202,12 +130,4 @@ RSpec.describe Gitlab::Metrics::Dashboard::Url do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#build_dashboard_url' do
|
||||
it 'builds the url for the dashboard endpoint' do
|
||||
url = described_class.build_dashboard_url('foo', 'bar', 1)
|
||||
|
||||
expect(url).to match described_class.metrics_regex
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -804,7 +804,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures, feature_category: :servic
|
|||
let(:project) { create(:project) }
|
||||
let(:description_with_embed) { "Some comment\n\nhttps://grafana.example.com/d/xvAk4q0Wk/go-processes?orgId=1&from=1573238522762&to=1573240322762&var-job=prometheus&var-interval=10m&panelId=1&fullscreen" }
|
||||
let(:description_with_unintegrated_embed) { "Some comment\n\nhttps://grafana.exp.com/d/xvAk4q0Wk/go-processes?orgId=1&from=1573238522762&to=1573240322762&var-job=prometheus&var-interval=10m&panelId=1&fullscreen" }
|
||||
let(:description_with_non_grafana_inline_metric) { "Some comment\n\n#{Gitlab::Routing.url_helpers.metrics_namespace_project_environment_url(*['foo', 'bar', 12])}" }
|
||||
|
||||
shared_examples "zero count" do
|
||||
it "does not count the issue" do
|
||||
|
|
@ -824,7 +823,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures, feature_category: :servic
|
|||
create(:issue, project: project, description: description_with_embed)
|
||||
# In-Valid
|
||||
create(:issue, project: project, description: description_with_unintegrated_embed)
|
||||
create(:issue, project: project, description: description_with_non_grafana_inline_metric)
|
||||
create(:issue, project: project, description: nil)
|
||||
create(:issue, project: project, description: '')
|
||||
create(:issue, project: project)
|
||||
|
|
|
|||
|
|
@ -104,7 +104,6 @@ RSpec.describe Emails::Projects do
|
|||
let_it_be(:environment) { create(:environment, project: project) }
|
||||
|
||||
let(:payload) { { 'gitlab_environment_name' => environment.name } }
|
||||
let(:metrics_url) { metrics_project_environment_url(project, environment) }
|
||||
|
||||
it_behaves_like 'an email sent from GitLab'
|
||||
it_behaves_like 'it should not have Gmail Actions links'
|
||||
|
|
@ -131,7 +130,6 @@ RSpec.describe Emails::Projects do
|
|||
|
||||
let(:alert) { create(:alert_management_alert, :prometheus, :from_payload, payload: payload, project: project) }
|
||||
let(:title) { "#{prometheus_alert.title} #{prometheus_alert.computed_operator} #{prometheus_alert.threshold}" }
|
||||
let(:metrics_url) { metrics_project_environment_url(project, environment) }
|
||||
|
||||
before do
|
||||
payload['labels'] = {
|
||||
|
|
@ -157,7 +155,6 @@ RSpec.describe Emails::Projects do
|
|||
is_expected.to have_body_text(environment.name)
|
||||
is_expected.to have_body_text('Metric:')
|
||||
is_expected.to have_body_text(prometheus_alert.full_query)
|
||||
is_expected.to have_body_text(metrics_url)
|
||||
is_expected.not_to have_body_text('Description:')
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9059,6 +9059,67 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
|
|||
end
|
||||
end
|
||||
|
||||
describe '.without_created_and_owned_by_banned_user' do
|
||||
let_it_be(:other_project) { create(:project) }
|
||||
|
||||
subject(:results) { described_class.without_created_and_owned_by_banned_user }
|
||||
|
||||
context 'when project creator is not banned' do
|
||||
let_it_be(:project_of_active_user) { create(:project, creator: create(:user)) }
|
||||
|
||||
it 'includes the project' do
|
||||
expect(results).to match_array([other_project, project_of_active_user])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when project creator is banned' do
|
||||
let_it_be(:banned_user) { create(:user, :banned) }
|
||||
let_it_be(:project_of_banned_user) { create(:project, creator: banned_user) }
|
||||
|
||||
context 'when project creator is also an owner' do
|
||||
let_it_be(:project_auth) do
|
||||
project = project_of_banned_user
|
||||
create(:project_authorization, :owner, user: project.creator, project: project)
|
||||
end
|
||||
|
||||
it 'excludes the project' do
|
||||
expect(results).to match_array([other_project])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when project creator is not an owner' do
|
||||
it 'includes the project' do
|
||||
expect(results).to match_array([other_project, project_of_banned_user])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#created_and_owned_by_banned_user?' do
|
||||
subject { project.created_and_owned_by_banned_user? }
|
||||
|
||||
context 'when creator is banned' do
|
||||
let_it_be(:creator) { create(:user, :banned) }
|
||||
let_it_be(:project) { create(:project, creator: creator) }
|
||||
|
||||
it { is_expected.to eq false }
|
||||
|
||||
context 'when creator is an owner' do
|
||||
let_it_be(:project_auth) do
|
||||
create(:project_authorization, :owner, user: project.creator, project: project)
|
||||
end
|
||||
|
||||
it { is_expected.to eq true }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when creator is not banned' do
|
||||
let_it_be(:project) { create(:project) }
|
||||
|
||||
it { is_expected.to eq false }
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'something that has web-hooks' do
|
||||
let_it_be_with_reload(:object) { create(:project) }
|
||||
|
||||
|
|
|
|||
|
|
@ -3217,6 +3217,32 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'when project is created and owned by a banned user' do
|
||||
let_it_be(:project) { create(:project, :public) }
|
||||
|
||||
let(:current_user) { guest }
|
||||
|
||||
before do
|
||||
allow(project).to receive(:created_and_owned_by_banned_user?).and_return(true)
|
||||
end
|
||||
|
||||
it { expect_disallowed(:read_project) }
|
||||
|
||||
context 'when current user is an admin', :enable_admin_mode do
|
||||
let(:current_user) { admin }
|
||||
|
||||
it { expect_allowed(:read_project) }
|
||||
end
|
||||
|
||||
context 'when hide_projects_of_banned_users FF is disabled' do
|
||||
before do
|
||||
stub_feature_flags(hide_projects_of_banned_users: false)
|
||||
end
|
||||
|
||||
it { expect_allowed(:read_project) }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def project_subject(project_type)
|
||||
|
|
|
|||
|
|
@ -40,12 +40,6 @@ RSpec.describe 'getting Alert Management Alert Assignees', feature_category: :in
|
|||
create(:alert_management_alert, :prometheus, project: project, payload: payload)
|
||||
end
|
||||
|
||||
it 'includes the correct metrics dashboard url' do
|
||||
post_graphql(graphql_query, current_user: current_user)
|
||||
|
||||
expect(first_alert).to include('metricsDashboardUrl' => dashboard_url_for_alert)
|
||||
end
|
||||
|
||||
context 'when metrics dashboard feature is unavailable' do
|
||||
before do
|
||||
stub_feature_flags(remove_monitor_metrics: true)
|
||||
|
|
|
|||
|
|
@ -106,6 +106,8 @@ RSpec.describe RuboCop::Formatter::TodoFormatter, feature_category: :tooling do
|
|||
Exclude:
|
||||
- 'd.rb'
|
||||
- 'app/views/project.html.haml.rb'
|
||||
- 'app/views/project.haml.rb'
|
||||
- 'app/views/project.text.haml.rb'
|
||||
- 'app/views/unrelated.html.haml.rb.ext'
|
||||
- 'app/views/unrelated.html.haml.ext'
|
||||
- 'app/views/unrelated.html.haml'
|
||||
|
|
@ -122,7 +124,9 @@ RSpec.describe RuboCop::Formatter::TodoFormatter, feature_category: :tooling do
|
|||
B/TooManyOffenses:
|
||||
Exclude:
|
||||
- 'a.rb'
|
||||
- 'app/views/project.haml.rb'
|
||||
- 'app/views/project.html.haml.rb'
|
||||
- 'app/views/project.text.haml.rb'
|
||||
- 'c.rb'
|
||||
YAML
|
||||
end
|
||||
|
|
|
|||
|
|
@ -83,32 +83,6 @@ RSpec.describe EnvironmentEntity do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when metrics dashboard feature is available' do
|
||||
before do
|
||||
stub_feature_flags(remove_monitor_metrics: false)
|
||||
end
|
||||
|
||||
context 'metrics disabled' do
|
||||
before do
|
||||
allow(environment).to receive(:has_metrics?).and_return(false)
|
||||
end
|
||||
|
||||
it "doesn't expose metrics path" do
|
||||
expect(subject).not_to include(:metrics_path)
|
||||
end
|
||||
end
|
||||
|
||||
context 'metrics enabled' do
|
||||
before do
|
||||
allow(environment).to receive(:has_metrics?).and_return(true)
|
||||
end
|
||||
|
||||
it 'exposes metrics path' do
|
||||
expect(subject).to include(:metrics_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "doesn't expose metrics path" do
|
||||
expect(subject).not_to include(:metrics_path)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ RSpec.describe Metrics::Dashboard::ClusterDashboardService, :use_clean_rails_mem
|
|||
end
|
||||
|
||||
describe '#get_dashboard' do
|
||||
let(:service_params) { [project, user, { cluster: cluster, cluster_type: :project }] }
|
||||
let(:service_params) { [project, user, { cluster: cluster, cluster_type: :admin }] }
|
||||
let(:service_call) { subject.get_dashboard }
|
||||
|
||||
subject { described_class.new(*service_params) }
|
||||
|
|
|
|||
|
|
@ -37,17 +37,6 @@ RSpec.shared_context 'self-managed prometheus alert attributes' do
|
|||
}
|
||||
}
|
||||
end
|
||||
|
||||
let(:dashboard_url_for_alert) do
|
||||
Gitlab::Routing.url_helpers.metrics_dashboard_project_environment_url(
|
||||
project,
|
||||
environment,
|
||||
embed_json: embed_content,
|
||||
embedded: true,
|
||||
end: '2018-03-12T09:36:00Z',
|
||||
start: '2018-03-12T08:36:00Z'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.shared_context 'gitlab-managed prometheus alert attributes' do
|
||||
|
|
|
|||
|
|
@ -12,33 +12,3 @@ RSpec.shared_examples_for 'GET #metrics_dashboard correctly formatted response'
|
|||
expect(found_keys).to contain_exactly(*expected_keys)
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.shared_examples_for 'GET #metrics_dashboard for dashboard' do |dashboard_name|
|
||||
let(:expected_keys) { %w(dashboard status metrics_data) }
|
||||
let(:status_code) { :ok }
|
||||
|
||||
before do
|
||||
stub_feature_flags(remove_monitor_metrics: false)
|
||||
end
|
||||
|
||||
it_behaves_like 'GET #metrics_dashboard correctly formatted response'
|
||||
|
||||
it 'returns correct dashboard' do
|
||||
get :metrics_dashboard, params: metrics_dashboard_req_params, format: :json
|
||||
|
||||
expect(json_response['dashboard']['dashboard']).to eq(dashboard_name)
|
||||
end
|
||||
|
||||
context 'when metrics dashboard feature is unavailable' do
|
||||
before do
|
||||
stub_feature_flags(remove_monitor_metrics: true)
|
||||
end
|
||||
|
||||
it 'returns 404 not found' do
|
||||
get :metrics_dashboard, params: metrics_dashboard_req_params, format: :json
|
||||
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
expect(response.body).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -572,7 +572,7 @@ RSpec.shared_examples 'edits content using the content editor' do |params = { wi
|
|||
|
||||
expect(find(suggestions_dropdown)).to have_text('My Cool Merge Request')
|
||||
|
||||
send_keys :enter
|
||||
send_keys [:arrow_down, :enter]
|
||||
|
||||
expect(page).not_to have_css(suggestions_dropdown)
|
||||
expect(page).to have_text('!1')
|
||||
|
|
@ -583,7 +583,7 @@ RSpec.shared_examples 'edits content using the content editor' do |params = { wi
|
|||
|
||||
expect(find(suggestions_dropdown)).to have_text('My Cool Linked Issue')
|
||||
|
||||
send_keys :enter
|
||||
send_keys [:arrow_down, :enter]
|
||||
|
||||
expect(page).not_to have_css(suggestions_dropdown)
|
||||
expect(page).to have_text('#1')
|
||||
|
|
@ -594,7 +594,7 @@ RSpec.shared_examples 'edits content using the content editor' do |params = { wi
|
|||
|
||||
expect(find(suggestions_dropdown)).to have_text('My Cool Milestone')
|
||||
|
||||
send_keys :enter
|
||||
send_keys [:arrow_down, :enter]
|
||||
|
||||
expect(page).not_to have_css(suggestions_dropdown)
|
||||
expect(page).to have_text('%My Cool Milestone')
|
||||
|
|
@ -606,7 +606,7 @@ RSpec.shared_examples 'edits content using the content editor' do |params = { wi
|
|||
expect(find(suggestions_dropdown)).to have_text('🙂 slight_smile')
|
||||
expect(find(suggestions_dropdown)).to have_text('😸 smile_cat')
|
||||
|
||||
send_keys :enter
|
||||
send_keys [:arrow_down, :enter]
|
||||
|
||||
expect(page).not_to have_css(suggestions_dropdown)
|
||||
|
||||
|
|
@ -636,7 +636,7 @@ RSpec.shared_examples 'edits content using the content editor' do |params = { wi
|
|||
end
|
||||
|
||||
def dropdown_scroll_top
|
||||
evaluate_script("document.querySelector('#{suggestions_dropdown} .gl-dropdown-inner').scrollTop")
|
||||
evaluate_script("document.querySelector('#{suggestions_dropdown}').scrollTop")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue