Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
69d62eae98
commit
b654eb44a8
|
@ -6,10 +6,12 @@ import {
|
||||||
GlSafeHtmlDirective as SafeHtml,
|
GlSafeHtmlDirective as SafeHtml,
|
||||||
} from '@gitlab/ui';
|
} from '@gitlab/ui';
|
||||||
import { mapActions } from 'vuex';
|
import { mapActions } from 'vuex';
|
||||||
import { __ } from '~/locale';
|
import { __, s__ } from '~/locale';
|
||||||
import timeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
import timeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||||
import UserNameWithStatus from '../../sidebar/components/assignees/user_name_with_status.vue';
|
import UserNameWithStatus from '../../sidebar/components/assignees/user_name_with_status.vue';
|
||||||
|
|
||||||
|
import { NOTEABLE_TYPE_MAPPING } from '../constants';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
safeHtmlConfig: { ADD_TAGS: ['gl-emoji'] },
|
safeHtmlConfig: { ADD_TAGS: ['gl-emoji'] },
|
||||||
components: {
|
components: {
|
||||||
|
@ -45,6 +47,11 @@ export default {
|
||||||
required: false,
|
required: false,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
noteableType: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
includeToggle: {
|
includeToggle: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
|
@ -103,6 +110,15 @@ export default {
|
||||||
authorName() {
|
authorName() {
|
||||||
return this.author.name;
|
return this.author.name;
|
||||||
},
|
},
|
||||||
|
noteConfidentialityTooltip() {
|
||||||
|
if (
|
||||||
|
this.noteableType === NOTEABLE_TYPE_MAPPING.Issue ||
|
||||||
|
this.noteableType === NOTEABLE_TYPE_MAPPING.MergeRequest
|
||||||
|
) {
|
||||||
|
return s__('Notes|This comment is confidential and only visible to project members');
|
||||||
|
}
|
||||||
|
return s__('Notes|This comment is confidential and only visible to group members');
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.emojiTitle = this.emojiElement ? this.emojiElement.getAttribute('title') : '';
|
this.emojiTitle = this.emojiElement ? this.emojiElement.getAttribute('title') : '';
|
||||||
|
@ -226,7 +242,7 @@ export default {
|
||||||
data-testid="confidentialIndicator"
|
data-testid="confidentialIndicator"
|
||||||
name="eye-slash"
|
name="eye-slash"
|
||||||
:size="16"
|
:size="16"
|
||||||
:title="s__('Notes|This comment is confidential and only visible to project members')"
|
:title="noteConfidentialityTooltip"
|
||||||
class="gl-ml-1 gl-text-orange-700 align-middle"
|
class="gl-ml-1 gl-text-orange-700 align-middle"
|
||||||
/>
|
/>
|
||||||
<slot name="extra-controls"></slot>
|
<slot name="extra-controls"></slot>
|
||||||
|
|
|
@ -432,6 +432,7 @@ export default {
|
||||||
:created-at="note.created_at"
|
:created-at="note.created_at"
|
||||||
:note-id="note.id"
|
:note-id="note.id"
|
||||||
:is-confidential="note.confidential"
|
:is-confidential="note.confidential"
|
||||||
|
:noteable-type="noteableType"
|
||||||
>
|
>
|
||||||
<template #note-header-info>
|
<template #note-header-info>
|
||||||
<slot name="note-header-info"></slot>
|
<slot name="note-header-info"></slot>
|
||||||
|
|
|
@ -32,6 +32,7 @@ class GraphqlController < ApplicationController
|
||||||
before_action :set_user_last_activity
|
before_action :set_user_last_activity
|
||||||
before_action :track_vs_code_usage
|
before_action :track_vs_code_usage
|
||||||
before_action :track_jetbrains_usage
|
before_action :track_jetbrains_usage
|
||||||
|
before_action :track_gitlab_cli_usage
|
||||||
before_action :disable_query_limiting
|
before_action :disable_query_limiting
|
||||||
before_action :limit_query_size
|
before_action :limit_query_size
|
||||||
|
|
||||||
|
@ -143,6 +144,11 @@ class GraphqlController < ApplicationController
|
||||||
.track_api_request_when_trackable(user_agent: request.user_agent, user: current_user)
|
.track_api_request_when_trackable(user_agent: request.user_agent, user: current_user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def track_gitlab_cli_usage
|
||||||
|
Gitlab::UsageDataCounters::GitLabCliActivityUniqueCounter
|
||||||
|
.track_api_request_when_trackable(user_agent: request.user_agent, user: current_user)
|
||||||
|
end
|
||||||
|
|
||||||
def execute_multiplex
|
def execute_multiplex
|
||||||
GitlabSchema.multiplex(multiplex_queries, context: context)
|
GitlabSchema.multiplex(multiplex_queries, context: context)
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,7 +10,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
||||||
include RecordUserLastActivity
|
include RecordUserLastActivity
|
||||||
|
|
||||||
ISSUES_EXCEPT_ACTIONS = %i[index calendar new create bulk_update import_csv export_csv service_desk].freeze
|
ISSUES_EXCEPT_ACTIONS = %i[index calendar new create bulk_update import_csv export_csv service_desk].freeze
|
||||||
SET_ISSUABLES_INDEX_ONLY_ACTIONS = %i[calendar service_desk].freeze
|
SET_ISSUABLES_INDEX_ONLY_ACTIONS = %i[index calendar service_desk].freeze
|
||||||
|
|
||||||
prepend_before_action(only: [:index]) { authenticate_sessionless_user!(:rss) }
|
prepend_before_action(only: [:index]) { authenticate_sessionless_user!(:rss) }
|
||||||
prepend_before_action(only: [:calendar]) { authenticate_sessionless_user!(:ics) }
|
prepend_before_action(only: [:calendar]) { authenticate_sessionless_user!(:ics) }
|
||||||
|
@ -22,7 +22,9 @@ class Projects::IssuesController < Projects::ApplicationController
|
||||||
before_action :issue, unless: ->(c) { ISSUES_EXCEPT_ACTIONS.include?(c.action_name.to_sym) }
|
before_action :issue, unless: ->(c) { ISSUES_EXCEPT_ACTIONS.include?(c.action_name.to_sym) }
|
||||||
after_action :log_issue_show, unless: ->(c) { ISSUES_EXCEPT_ACTIONS.include?(c.action_name.to_sym) }
|
after_action :log_issue_show, unless: ->(c) { ISSUES_EXCEPT_ACTIONS.include?(c.action_name.to_sym) }
|
||||||
|
|
||||||
before_action :set_issuables_index, if: ->(c) { SET_ISSUABLES_INDEX_ONLY_ACTIONS.include?(c.action_name.to_sym) }
|
before_action :set_issuables_index, if: ->(c) {
|
||||||
|
SET_ISSUABLES_INDEX_ONLY_ACTIONS.include?(c.action_name.to_sym) && !vue_issues_list?
|
||||||
|
}
|
||||||
|
|
||||||
# Allow write(create) issue
|
# Allow write(create) issue
|
||||||
before_action :authorize_create_issue!, only: [:new, :create]
|
before_action :authorize_create_issue!, only: [:new, :create]
|
||||||
|
@ -71,10 +73,9 @@ class Projects::IssuesController < Projects::ApplicationController
|
||||||
attr_accessor :vulnerability_id
|
attr_accessor :vulnerability_id
|
||||||
|
|
||||||
def index
|
def index
|
||||||
if html_request? && Feature.enabled?(:vue_issues_list, project&.group, default_enabled: :yaml)
|
if vue_issues_list?
|
||||||
set_sort_order
|
set_sort_order
|
||||||
else
|
else
|
||||||
set_issuables_index
|
|
||||||
@issues = @issuables
|
@issues = @issuables
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -248,6 +249,12 @@ class Projects::IssuesController < Projects::ApplicationController
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
|
def vue_issues_list?
|
||||||
|
action_name.to_sym == :index &&
|
||||||
|
html_request? &&
|
||||||
|
Feature.enabled?(:vue_issues_list, project&.group, default_enabled: :yaml)
|
||||||
|
end
|
||||||
|
|
||||||
def sorting_field
|
def sorting_field
|
||||||
Issue::SORTING_PREFERENCE_FIELD
|
Issue::SORTING_PREFERENCE_FIELD
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,9 +6,8 @@ module Releases
|
||||||
#
|
#
|
||||||
# order_by - only ordering by released_at is supported
|
# order_by - only ordering by released_at is supported
|
||||||
# filter by tag - currently not supported
|
# filter by tag - currently not supported
|
||||||
|
# include_subgroups - always true for group releases finder
|
||||||
class GroupReleasesFinder
|
class GroupReleasesFinder
|
||||||
include Gitlab::Utils::StrongMemoize
|
|
||||||
|
|
||||||
attr_reader :parent, :current_user, :params
|
attr_reader :parent, :current_user, :params
|
||||||
|
|
||||||
def initialize(parent, current_user = nil, params = {})
|
def initialize(parent, current_user = nil, params = {})
|
||||||
|
@ -25,45 +24,26 @@ module Releases
|
||||||
def execute(preload: true)
|
def execute(preload: true)
|
||||||
return Release.none unless Ability.allowed?(current_user, :read_release, parent)
|
return Release.none unless Ability.allowed?(current_user, :read_release, parent)
|
||||||
|
|
||||||
releases = get_releases(preload: preload)
|
releases = get_releases
|
||||||
|
releases.preloaded if preload
|
||||||
paginate_releases(releases)
|
paginate_releases(releases)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def include_subgroups?
|
|
||||||
params.fetch(:include_subgroups, false)
|
|
||||||
end
|
|
||||||
|
|
||||||
def accessible_projects_scope
|
|
||||||
if include_subgroups?
|
|
||||||
Project.for_group_and_its_subgroups(parent)
|
|
||||||
else
|
|
||||||
parent.projects
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# rubocop: disable CodeReuse/ActiveRecord
|
# rubocop: disable CodeReuse/ActiveRecord
|
||||||
def get_releases(preload: true)
|
def get_releases
|
||||||
Gitlab::Pagination::Keyset::InOperatorOptimization::QueryBuilder.new(
|
Gitlab::Pagination::Keyset::InOperatorOptimization::QueryBuilder.new(
|
||||||
scope: releases_scope(preload: preload),
|
scope: releases_scope,
|
||||||
array_scope: accessible_projects_scope.select(:id),
|
array_scope: Project.for_group_and_its_subgroups(parent).select(:id),
|
||||||
array_mapping_scope: -> (project_id_expression) { Release.where(Release.arel_table[:project_id].eq(project_id_expression)) },
|
array_mapping_scope: -> (project_id_expression) { Release.where(Release.arel_table[:project_id].eq(project_id_expression)) },
|
||||||
finder_query: -> (order_by, id_expression) { Release.where(Release.arel_table[:id].eq(id_expression)) }
|
finder_query: -> (order_by, id_expression) { Release.where(Release.arel_table[:id].eq(id_expression)) }
|
||||||
)
|
)
|
||||||
.execute
|
.execute
|
||||||
end
|
end
|
||||||
|
|
||||||
def releases_scope(preload: true)
|
def releases_scope
|
||||||
scope = Release.all
|
Release.sort_by_attribute("released_at_#{params[:sort]}").order(id: params[:sort])
|
||||||
scope = order_releases(scope)
|
|
||||||
scope = scope.preloaded if preload
|
|
||||||
scope
|
|
||||||
end
|
|
||||||
|
|
||||||
def order_releases(scope)
|
|
||||||
scope.sort_by_attribute("released_at_#{params[:sort]}").order(id: params[:sort])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def paginate_releases(releases)
|
def paginate_releases(releases)
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
%h5.gl-mt-0
|
%h5.gl-mt-0
|
||||||
= _('Add an SSH key')
|
= _('Add an SSH key')
|
||||||
%p.profile-settings-content
|
%p.profile-settings-content
|
||||||
- help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('ssh/index.md') }
|
- help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/ssh.md') }
|
||||||
= _('Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}').html_safe % {help_link_start: help_link_start, help_link_end: '</a>'.html_safe }
|
= _('Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}').html_safe % {help_link_start: help_link_start, help_link_end: '</a>'.html_safe }
|
||||||
= render 'form'
|
= render 'form'
|
||||||
%hr
|
%hr
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
name: usage_data_i_code_review_user_gitlab_cli_api_request
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83464
|
||||||
|
rollout_issue_url:
|
||||||
|
milestone: '14.10'
|
||||||
|
type: development
|
||||||
|
group: group::code review
|
||||||
|
default_enabled: true
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
name: user_other_role_details
|
name: user_other_role_details
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45635
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45635
|
||||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/255170
|
rollout_issue_url: https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/282
|
||||||
milestone: '13.7'
|
milestone: '13.7'
|
||||||
type: development
|
type: development
|
||||||
group: group::conversion
|
group: group::conversion
|
||||||
|
|
|
@ -25,6 +25,7 @@ Rails.autoloaders.each do |autoloader|
|
||||||
'cidr' => 'CIDR',
|
'cidr' => 'CIDR',
|
||||||
'cli' => 'CLI',
|
'cli' => 'CLI',
|
||||||
'dn' => 'DN',
|
'dn' => 'DN',
|
||||||
|
'gitlab_cli_activity_unique_counter' => 'GitLabCliActivityUniqueCounter',
|
||||||
'global_id_type' => 'GlobalIDType',
|
'global_id_type' => 'GlobalIDType',
|
||||||
'global_id_compatibility' => 'GlobalIDCompatibility',
|
'global_id_compatibility' => 'GlobalIDCompatibility',
|
||||||
'hll' => 'HLL',
|
'hll' => 'HLL',
|
||||||
|
|
|
@ -74,6 +74,7 @@
|
||||||
- 'i_code_review_post_merge_submit_revert_modal'
|
- 'i_code_review_post_merge_submit_revert_modal'
|
||||||
- 'i_code_review_post_merge_submit_cherry_pick_modal'
|
- 'i_code_review_post_merge_submit_cherry_pick_modal'
|
||||||
- 'i_code_review_user_jetbrains_api_request'
|
- 'i_code_review_user_jetbrains_api_request'
|
||||||
|
- 'i_code_review_user_gitlab_cli_api_request'
|
||||||
- name: code_review_category_monthly_active_users
|
- name: code_review_category_monthly_active_users
|
||||||
operator: OR
|
operator: OR
|
||||||
source: redis
|
source: redis
|
||||||
|
@ -146,3 +147,4 @@
|
||||||
events:
|
events:
|
||||||
- 'i_code_review_user_vs_code_api_request'
|
- 'i_code_review_user_vs_code_api_request'
|
||||||
- 'i_code_review_user_jetbrains_api_request'
|
- 'i_code_review_user_jetbrains_api_request'
|
||||||
|
- 'i_code_review_user_gitlab_cli_api_request'
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
---
|
||||||
|
key_path: redis_hll_counters.code_review.i_code_review_user_gitlab_cli_api_request_monthly
|
||||||
|
description: Count of unique users per month who use the GitLab CLI
|
||||||
|
product_section: dev
|
||||||
|
product_stage: create
|
||||||
|
product_group: group::code review
|
||||||
|
product_category: editor_extension
|
||||||
|
value_type: number
|
||||||
|
status: active
|
||||||
|
milestone: "14.10"
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83464
|
||||||
|
time_frame: 28d
|
||||||
|
data_source: redis_hll
|
||||||
|
data_category: optional
|
||||||
|
instrumentation_class: RedisHLLMetric
|
||||||
|
options:
|
||||||
|
events:
|
||||||
|
- i_code_review_user_gitlab_cli_api_request
|
||||||
|
performance_indicator_type: []
|
||||||
|
distribution:
|
||||||
|
- ce
|
||||||
|
- ee
|
||||||
|
tier:
|
||||||
|
- free
|
||||||
|
- premium
|
||||||
|
- ultimate
|
|
@ -0,0 +1,26 @@
|
||||||
|
---
|
||||||
|
key_path: redis_hll_counters.code_review.i_code_review_user_gitlab_cli_api_request_weekly
|
||||||
|
description: Count of unique users per week who use the GitLab CLI
|
||||||
|
product_section: dev
|
||||||
|
product_stage: create
|
||||||
|
product_group: group::code review
|
||||||
|
product_category: editor_extension
|
||||||
|
value_type: number
|
||||||
|
status: active
|
||||||
|
milestone: "14.10"
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83464
|
||||||
|
time_frame: 7d
|
||||||
|
data_source: redis_hll
|
||||||
|
data_category: optional
|
||||||
|
instrumentation_class: RedisHLLMetric
|
||||||
|
options:
|
||||||
|
events:
|
||||||
|
- i_code_review_user_gitlab_cli_api_request
|
||||||
|
performance_indicator_type: []
|
||||||
|
distribution:
|
||||||
|
- ce
|
||||||
|
- ee
|
||||||
|
tier:
|
||||||
|
- free
|
||||||
|
- premium
|
||||||
|
- ultimate
|
|
@ -1458,7 +1458,7 @@ Input type: `CreateIssueInput`
|
||||||
|
|
||||||
WARNING:
|
WARNING:
|
||||||
**Deprecated** in 14.0.
|
**Deprecated** in 14.0.
|
||||||
Use iterationCreate.
|
Manual iteration management is deprecated. Only automatic iteration cadences will be supported in the future.
|
||||||
|
|
||||||
Input type: `CreateIterationInput`
|
Input type: `CreateIterationInput`
|
||||||
|
|
||||||
|
@ -1470,7 +1470,7 @@ Input type: `CreateIterationInput`
|
||||||
| <a id="mutationcreateiterationdescription"></a>`description` | [`String`](#string) | Description of the iteration. |
|
| <a id="mutationcreateiterationdescription"></a>`description` | [`String`](#string) | Description of the iteration. |
|
||||||
| <a id="mutationcreateiterationduedate"></a>`dueDate` | [`String`](#string) | End date of the iteration. |
|
| <a id="mutationcreateiterationduedate"></a>`dueDate` | [`String`](#string) | End date of the iteration. |
|
||||||
| <a id="mutationcreateiterationgrouppath"></a>`groupPath` | [`ID`](#id) | Full path of the group with which the resource is associated. |
|
| <a id="mutationcreateiterationgrouppath"></a>`groupPath` | [`ID`](#id) | Full path of the group with which the resource is associated. |
|
||||||
| <a id="mutationcreateiterationiterationscadenceid"></a>`iterationsCadenceId` | [`IterationsCadenceID`](#iterationscadenceid) | Global ID of the iterations cadence to be assigned to newly created iteration. |
|
| <a id="mutationcreateiterationiterationscadenceid"></a>`iterationsCadenceId` **{warning-solid}** | [`IterationsCadenceID`](#iterationscadenceid) | **Deprecated:** `iterationCadenceId` is deprecated and will be removed in the future. This argument is ignored, because you can't create an iteration in a specific cadence. In the future only automatic iteration cadences will be allowed. Deprecated in 14.10. |
|
||||||
| <a id="mutationcreateiterationprojectpath"></a>`projectPath` | [`ID`](#id) | Full path of the project with which the resource is associated. |
|
| <a id="mutationcreateiterationprojectpath"></a>`projectPath` | [`ID`](#id) | Full path of the project with which the resource is associated. |
|
||||||
| <a id="mutationcreateiterationstartdate"></a>`startDate` | [`String`](#string) | Start date of the iteration. |
|
| <a id="mutationcreateiterationstartdate"></a>`startDate` | [`String`](#string) | Start date of the iteration. |
|
||||||
| <a id="mutationcreateiterationtitle"></a>`title` | [`String`](#string) | Title of the iteration. |
|
| <a id="mutationcreateiterationtitle"></a>`title` | [`String`](#string) | Title of the iteration. |
|
||||||
|
@ -3213,6 +3213,10 @@ Input type: `IterationCadenceUpdateInput`
|
||||||
|
|
||||||
### `Mutation.iterationCreate`
|
### `Mutation.iterationCreate`
|
||||||
|
|
||||||
|
WARNING:
|
||||||
|
**Deprecated** in 14.10.
|
||||||
|
Manual iteration management is deprecated. Only automatic iteration cadences will be supported in the future.
|
||||||
|
|
||||||
Input type: `iterationCreateInput`
|
Input type: `iterationCreateInput`
|
||||||
|
|
||||||
#### Arguments
|
#### Arguments
|
||||||
|
@ -3223,7 +3227,7 @@ Input type: `iterationCreateInput`
|
||||||
| <a id="mutationiterationcreatedescription"></a>`description` | [`String`](#string) | Description of the iteration. |
|
| <a id="mutationiterationcreatedescription"></a>`description` | [`String`](#string) | Description of the iteration. |
|
||||||
| <a id="mutationiterationcreateduedate"></a>`dueDate` | [`String`](#string) | End date of the iteration. |
|
| <a id="mutationiterationcreateduedate"></a>`dueDate` | [`String`](#string) | End date of the iteration. |
|
||||||
| <a id="mutationiterationcreategrouppath"></a>`groupPath` | [`ID`](#id) | Full path of the group with which the resource is associated. |
|
| <a id="mutationiterationcreategrouppath"></a>`groupPath` | [`ID`](#id) | Full path of the group with which the resource is associated. |
|
||||||
| <a id="mutationiterationcreateiterationscadenceid"></a>`iterationsCadenceId` | [`IterationsCadenceID`](#iterationscadenceid) | Global ID of the iterations cadence to be assigned to newly created iteration. |
|
| <a id="mutationiterationcreateiterationscadenceid"></a>`iterationsCadenceId` **{warning-solid}** | [`IterationsCadenceID`](#iterationscadenceid) | **Deprecated:** `iterationCadenceId` is deprecated and will be removed in the future. This argument is ignored, because you can't create an iteration in a specific cadence. In the future only automatic iteration cadences will be allowed. Deprecated in 14.10. |
|
||||||
| <a id="mutationiterationcreateprojectpath"></a>`projectPath` | [`ID`](#id) | Full path of the project with which the resource is associated. |
|
| <a id="mutationiterationcreateprojectpath"></a>`projectPath` | [`ID`](#id) | Full path of the project with which the resource is associated. |
|
||||||
| <a id="mutationiterationcreatestartdate"></a>`startDate` | [`String`](#string) | Start date of the iteration. |
|
| <a id="mutationiterationcreatestartdate"></a>`startDate` | [`String`](#string) | Start date of the iteration. |
|
||||||
| <a id="mutationiterationcreatetitle"></a>`title` | [`String`](#string) | Title of the iteration. |
|
| <a id="mutationiterationcreatetitle"></a>`title` | [`String`](#string) | Title of the iteration. |
|
||||||
|
|
|
@ -12,6 +12,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
||||||
> - Moved to GitLab Premium in 13.9.
|
> - Moved to GitLab Premium in 13.9.
|
||||||
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/221047) in GitLab 14.6. [Feature flag `group_iterations`](https://gitlab.com/gitlab-org/gitlab/-/issues/221047) removed.
|
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/221047) in GitLab 14.6. [Feature flag `group_iterations`](https://gitlab.com/gitlab-org/gitlab/-/issues/221047) removed.
|
||||||
|
|
||||||
|
WARNING:
|
||||||
|
After [Iteration Cadences](#iteration-cadences) becomes generally available,
|
||||||
|
manual iteration scheduling will be [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/356069) in GitLab 15.6.
|
||||||
|
To enhance the role of iterations as time boundaries, we will also deprecate the title field.
|
||||||
|
|
||||||
Iterations are a way to track issues over a period of time. This allows teams
|
Iterations are a way to track issues over a period of time. This allows teams
|
||||||
to track velocity and volatility metrics. Iterations can be used with [milestones](../../project/milestones/index.md)
|
to track velocity and volatility metrics. Iterations can be used with [milestones](../../project/milestones/index.md)
|
||||||
for tracking over different time periods.
|
for tracking over different time periods.
|
||||||
|
@ -28,54 +33,6 @@ In GitLab, iterations are similar to milestones, with a few differences:
|
||||||
- Iterations require both a start and an end date.
|
- Iterations require both a start and an end date.
|
||||||
- Iteration date ranges cannot overlap.
|
- Iteration date ranges cannot overlap.
|
||||||
|
|
||||||
## Iteration cadences
|
|
||||||
|
|
||||||
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5077) in GitLab 14.1.
|
|
||||||
> - Deployed behind a [feature flag](../../feature_flags.md), disabled by default.
|
|
||||||
> - Disabled on GitLab.com.
|
|
||||||
> - Not recommended for production use.
|
|
||||||
> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-iteration-cadences).
|
|
||||||
|
|
||||||
This in-development feature might not be available for your use. There can be
|
|
||||||
[risks when enabling features still in development](../../../administration/feature_flags.md#risks-when-enabling-features-still-in-development).
|
|
||||||
Refer to this feature's version history for more details.
|
|
||||||
|
|
||||||
Iteration cadences automate some common iteration tasks. They can be used to
|
|
||||||
automatically create iterations every 1, 2, 3, 4, or 6 weeks. They can also
|
|
||||||
be configured to automatically roll over incomplete issues to the next iteration.
|
|
||||||
|
|
||||||
With iteration cadences enabled, you must first
|
|
||||||
[create an iteration cadence](#create-an-iteration-cadence) before you can
|
|
||||||
[create an iteration](#create-an-iteration).
|
|
||||||
|
|
||||||
### Create an iteration cadence
|
|
||||||
|
|
||||||
Prerequisites:
|
|
||||||
|
|
||||||
- You must have at least the Developer role for a group.
|
|
||||||
|
|
||||||
To create an iteration cadence:
|
|
||||||
|
|
||||||
1. On the top bar, select **Menu > Groups** and find your group.
|
|
||||||
1. On the left sidebar, select **Issues > Iterations**.
|
|
||||||
1. Select **New iteration cadence**.
|
|
||||||
1. Fill out required fields, and select **Create iteration cadence**. The cadence list page opens.
|
|
||||||
|
|
||||||
### Delete an iteration cadence
|
|
||||||
|
|
||||||
Prerequisites:
|
|
||||||
|
|
||||||
- You must have at least the Developer role for a group.
|
|
||||||
|
|
||||||
Deleting an iteration cadence also deletes all iterations within that cadence.
|
|
||||||
|
|
||||||
To delete an iteration cadence:
|
|
||||||
|
|
||||||
1. On the top bar, select **Menu > Groups** and find your group.
|
|
||||||
1. On the left sidebar, select **Issues > Iterations**.
|
|
||||||
1. Select the three-dot menu (**{ellipsis_v}**) > **Delete cadence** for the cadence you want to delete.
|
|
||||||
1. Select **Delete cadence** in the confirmation modal.
|
|
||||||
|
|
||||||
## View the iterations list
|
## View the iterations list
|
||||||
|
|
||||||
To view the iterations list, go to **{issues}** **Issues > Iterations**.
|
To view the iterations list, go to **{issues}** **Issues > Iterations**.
|
||||||
|
@ -94,8 +51,6 @@ Prerequisites:
|
||||||
|
|
||||||
- You must have at least the Developer role for a group.
|
- You must have at least the Developer role for a group.
|
||||||
|
|
||||||
For manually scheduled iteration cadences, you create and add iterations yourself.
|
|
||||||
|
|
||||||
To create an iteration:
|
To create an iteration:
|
||||||
|
|
||||||
1. On the top bar, select **Menu > Groups** and find your group.
|
1. On the top bar, select **Menu > Groups** and find your group.
|
||||||
|
@ -153,7 +108,7 @@ The report also shows a breakdown of total issues in an iteration.
|
||||||
Open iteration reports show a summary of completed, unstarted, and in-progress issues.
|
Open iteration reports show a summary of completed, unstarted, and in-progress issues.
|
||||||
Closed iteration reports show the total number of issues completed by the due date.
|
Closed iteration reports show the total number of issues completed by the due date.
|
||||||
|
|
||||||
To view an iteration report, go to the iterations list page and select an iteration's title.
|
To view an iteration report, go to the iterations list page and select an iteration's period.
|
||||||
|
|
||||||
### Iteration burndown and burnup charts
|
### Iteration burndown and burnup charts
|
||||||
|
|
||||||
|
@ -212,33 +167,61 @@ To group issues by label:
|
||||||
You can also search for labels by typing in the search input.
|
You can also search for labels by typing in the search input.
|
||||||
1. Select any area outside the label dropdown list. The page is now grouped by the selected labels.
|
1. Select any area outside the label dropdown list. The page is now grouped by the selected labels.
|
||||||
|
|
||||||
### Enable or disable iteration cadences **(PREMIUM SELF)**
|
## Iteration cadences
|
||||||
|
|
||||||
Iteration Cadences feature is under development and not ready for production use. It is
|
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5077) in GitLab 14.1.
|
||||||
deployed behind a feature flag that is **disabled by default**.
|
> - Deployed behind a [feature flag](../../feature_flags.md), named `iteration_cadences`, disabled by default.
|
||||||
[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
|
|
||||||
can enable it.
|
|
||||||
|
|
||||||
To enable it:
|
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
|
||||||
|
`iteration_cadences` for a root group.
|
||||||
|
On GitLab.com, this feature is not available. This feature is not ready for production use.
|
||||||
|
|
||||||
```ruby
|
Iteration cadences automate iteration scheduling. You can use them to
|
||||||
Feature.enable(:iteration_cadences)
|
automate creating iterations every 1, 2, 3, 4, or 6 weeks. You can also
|
||||||
```
|
configure iteration cadences to automatically roll over incomplete issues to the next iteration.
|
||||||
|
|
||||||
To disable it:
|
### Create an iteration cadence
|
||||||
|
|
||||||
```ruby
|
Prerequisites:
|
||||||
Feature.disable(:iteration_cadences)
|
|
||||||
```
|
|
||||||
|
|
||||||
<!-- ## Troubleshooting
|
- You must have at least the Developer role for a group.
|
||||||
|
|
||||||
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
|
To create an iteration cadence:
|
||||||
one might have when setting this up, or when something is changed, or on upgrading, it's
|
|
||||||
important to describe those, too. Think of things that may go wrong and include them here.
|
|
||||||
This is important to minimize requests for support, and to avoid doc comments with
|
|
||||||
questions that you know someone might ask.
|
|
||||||
|
|
||||||
Each scenario can be a third-level heading, e.g. `### Getting error message X`.
|
1. On the top bar, select **Menu > Groups** and find your group.
|
||||||
If you have none to add when creating a doc, leave this section in place
|
1. On the left sidebar, select **Issues > Iterations**.
|
||||||
but commented out to help encourage others to add to it in the future. -->
|
1. Select **New iteration cadence**.
|
||||||
|
1. Fill out required fields, and select **Create iteration cadence**. The cadence list page opens.
|
||||||
|
|
||||||
|
### Delete an iteration cadence
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- You must have at least the Developer role for a group.
|
||||||
|
|
||||||
|
Deleting an iteration cadence also deletes all iterations within that cadence.
|
||||||
|
|
||||||
|
To delete an iteration cadence:
|
||||||
|
|
||||||
|
1. On the top bar, select **Menu > Groups** and find your group.
|
||||||
|
1. On the left sidebar, select **Issues > Iterations**.
|
||||||
|
1. Select the three-dot menu (**{ellipsis_v}**) > **Delete cadence** for the cadence you want to delete.
|
||||||
|
1. Select **Delete cadence** in the confirmation modal.
|
||||||
|
|
||||||
|
### Convert manual cadence to use automatic scheduling
|
||||||
|
|
||||||
|
WARNING:
|
||||||
|
The upgrade is irreversible. After it's done, manual iteration cadences cannot be created.
|
||||||
|
|
||||||
|
When you **enable** the iteration cadences feature, all iterations are added
|
||||||
|
to a default iteration cadence.
|
||||||
|
In this default iteration cadence, you can continue to add, edit, and remove iterations.
|
||||||
|
|
||||||
|
To upgrade the iteration cadence to use the automation features:
|
||||||
|
|
||||||
|
1. On the top bar, select **Menu > Groups** and find your group.
|
||||||
|
1. On the left sidebar, select **Issues > Iterations**.
|
||||||
|
1. Select the three-dot menu (**{ellipsis_v}**) > **Edit cadence** for the cadence you want to upgrade.
|
||||||
|
1. Fill out required fields, and select **Save changes**.
|
||||||
|
|
|
@ -80,6 +80,10 @@ module API
|
||||||
Gitlab::UsageDataCounters::JetBrainsPluginActivityUniqueCounter.track_api_request_when_trackable(user_agent: request&.user_agent, user: @current_user)
|
Gitlab::UsageDataCounters::JetBrainsPluginActivityUniqueCounter.track_api_request_when_trackable(user_agent: request&.user_agent, user: @current_user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
Gitlab::UsageDataCounters::GitLabCliActivityUniqueCounter.track_api_request_when_trackable(user_agent: request&.user_agent, user: @current_user)
|
||||||
|
end
|
||||||
|
|
||||||
# The locale is set to the current user's locale when `current_user` is loaded
|
# The locale is set to the current user's locale when `current_user` is loaded
|
||||||
after { Gitlab::I18n.use_default_locale }
|
after { Gitlab::I18n.use_default_locale }
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Gitlab
|
||||||
|
module UsageDataCounters
|
||||||
|
module GitLabCliActivityUniqueCounter
|
||||||
|
GITLAB_CLI_API_REQUEST_ACTION = 'i_code_review_user_gitlab_cli_api_request'
|
||||||
|
GITLAB_CLI_USER_AGENT_REGEX = /GitLab\sCLI$/.freeze
|
||||||
|
|
||||||
|
class << self
|
||||||
|
def track_api_request_when_trackable(user_agent:, user:)
|
||||||
|
user_agent&.match?(GITLAB_CLI_USER_AGENT_REGEX) && track_unique_action_by_user(GITLAB_CLI_API_REQUEST_ACTION, user)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def track_unique_action_by_user(action, user)
|
||||||
|
return unless user
|
||||||
|
|
||||||
|
track_unique_action(action, user.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def track_unique_action(action, value)
|
||||||
|
Gitlab::UsageDataCounters::HLLRedisCounter.track_usage_event(action, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -132,6 +132,11 @@
|
||||||
category: code_review
|
category: code_review
|
||||||
aggregation: weekly
|
aggregation: weekly
|
||||||
feature_flag: usage_data_i_code_review_user_jetbrains_api_request
|
feature_flag: usage_data_i_code_review_user_jetbrains_api_request
|
||||||
|
- name: i_code_review_user_gitlab_cli_api_request
|
||||||
|
redis_slot: code_review
|
||||||
|
category: code_review
|
||||||
|
aggregation: weekly
|
||||||
|
feature_flag: usage_data_i_code_review_user_gitlab_cli_api_request
|
||||||
- name: i_code_review_user_create_mr_from_issue
|
- name: i_code_review_user_create_mr_from_issue
|
||||||
redis_slot: code_review
|
redis_slot: code_review
|
||||||
category: code_review
|
category: code_review
|
||||||
|
|
|
@ -21107,10 +21107,13 @@ msgstr ""
|
||||||
msgid "Iterations"
|
msgid "Iterations"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Iterations|Add a duration, and number of future iterations in order to convert this cadence to automatic scheduling."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Iterations|Add iteration"
|
msgid "Iterations|Add iteration"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Iterations|Automated scheduling"
|
msgid "Iterations|All"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Iterations|Cadence configuration is invalid."
|
msgid "Iterations|Cadence configuration is invalid."
|
||||||
|
@ -21125,12 +21128,6 @@ msgstr ""
|
||||||
msgid "Iterations|Create cadence"
|
msgid "Iterations|Create cadence"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Iterations|Create cadence and start iteration"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Iterations|Create iteration"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Iterations|Delete cadence"
|
msgid "Iterations|Delete cadence"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -21140,6 +21137,9 @@ msgstr ""
|
||||||
msgid "Iterations|Delete iteration?"
|
msgid "Iterations|Delete iteration?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Iterations|Done"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Iterations|Duration"
|
msgid "Iterations|Duration"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -21161,10 +21161,13 @@ msgstr ""
|
||||||
msgid "Iterations|Iteration cadences"
|
msgid "Iterations|Iteration cadences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Iterations|Iteration scheduling will be handled automatically"
|
msgid "Iterations|Iterations are a way to track issues over a period of time, allowing teams to also track velocity and volatility metrics."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Iterations|Iterations are a way to track issues over a period of time, allowing teams to also track velocity and volatility metrics."
|
msgid "Iterations|Iterations can no longer be scheduled manually. Convert all cadences to automatic scheduling to keep your iterations working as expected."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Iterations|Learn more about automatic scheduling"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Iterations|Move incomplete issues to the next iteration"
|
msgid "Iterations|Move incomplete issues to the next iteration"
|
||||||
|
@ -21194,10 +21197,16 @@ msgstr ""
|
||||||
msgid "Iterations|Number of future iterations you would like to have scheduled"
|
msgid "Iterations|Number of future iterations you would like to have scheduled"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Iterations|Open"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Iterations|Requires update"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Iterations|Roll over issues"
|
msgid "Iterations|Roll over issues"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Iterations|Save cadence"
|
msgid "Iterations|Save changes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Iterations|Select duration"
|
msgid "Iterations|Select duration"
|
||||||
|
@ -21209,6 +21218,9 @@ msgstr ""
|
||||||
msgid "Iterations|Select start date"
|
msgid "Iterations|Select start date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Iterations|Some of your cadences need to be updated"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Iterations|Start date"
|
msgid "Iterations|Start date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -21221,6 +21233,9 @@ msgstr ""
|
||||||
msgid "Iterations|The start date of your first iteration"
|
msgid "Iterations|The start date of your first iteration"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Iterations|This cadence requires an update"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Iterations|This will delete the cadence as well as all of the iterations within it."
|
msgid "Iterations|This will delete the cadence as well as all of the iterations within it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -25646,6 +25661,9 @@ msgstr ""
|
||||||
msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
|
msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Notes|This comment is confidential and only visible to group members"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Notes|This comment is confidential and only visible to project members"
|
msgid "Notes|This comment is confidential and only visible to project members"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ module QA
|
||||||
Logger.debug('Getting repository storage moves')
|
Logger.debug('Getting repository storage moves')
|
||||||
|
|
||||||
Support::Waiter.wait_until do
|
Support::Waiter.wait_until do
|
||||||
with_paginated_response_body(Request.new(api_client, "/#{resource_name(resource)}_repository_storage_moves", per_page: '100').url) do |page|
|
get(Request.new(api_client, "/#{resource_name(resource)}_repository_storage_moves", per_page: '100').url) do |page|
|
||||||
break true if page.any? { |item| yield item }
|
break true if page.any? { |item| yield item }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
module QA
|
module QA
|
||||||
RSpec.describe 'Create' do
|
RSpec.describe 'Create' do
|
||||||
describe 'Changing Gitaly repository storage', :requires_admin do
|
describe 'Changing Gitaly repository storage', :requires_admin, except: { job: 'review-qa-*' } do
|
||||||
praefect_manager = Service::PraefectManager.new
|
praefect_manager = Service::PraefectManager.new
|
||||||
|
|
||||||
shared_examples 'repository storage move' do
|
shared_examples 'repository storage move' do
|
||||||
|
@ -11,12 +11,16 @@ module QA
|
||||||
expect { project.change_repository_storage(destination_storage[:name]) }.not_to raise_error
|
expect { project.change_repository_storage(destination_storage[:name]) }.not_to raise_error
|
||||||
expect { praefect_manager.verify_storage_move(source_storage, destination_storage, repo_type: :project) }.not_to raise_error
|
expect { praefect_manager.verify_storage_move(source_storage, destination_storage, repo_type: :project) }.not_to raise_error
|
||||||
|
|
||||||
Resource::Repository::ProjectPush.fabricate! do |push|
|
Support::Retrier.retry_on_exception(sleep_interval: 5) do
|
||||||
push.project = project
|
# For a short period of time after migrating, the repository can be 'read only' which may lead to errors
|
||||||
push.file_name = 'new_file'
|
# 'The repository is temporarily read-only. Please try again later.'
|
||||||
push.file_content = '# This is a new file'
|
Resource::Repository::Commit.fabricate_via_api! do |commit|
|
||||||
push.commit_message = 'Add new file'
|
commit.project = project
|
||||||
push.new_branch = false
|
commit.commit_message = 'Add new file'
|
||||||
|
commit.add_files([
|
||||||
|
{ file_path: 'new_file', content: '# This is a new file' }
|
||||||
|
])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(project).to have_file('README.md')
|
expect(project).to have_file('README.md')
|
||||||
|
@ -45,7 +49,7 @@ module QA
|
||||||
# Note: This test doesn't have the :orchestrated tag because it runs in the Test::Integration::Praefect
|
# Note: This test doesn't have the :orchestrated tag because it runs in the Test::Integration::Praefect
|
||||||
# scenario with other tests that aren't considered orchestrated.
|
# scenario with other tests that aren't considered orchestrated.
|
||||||
# It also runs on staging using nfs-file07 as non-cluster storage and nfs-file22 as cluster/praefect storage
|
# It also runs on staging using nfs-file07 as non-cluster storage and nfs-file22 as cluster/praefect storage
|
||||||
context 'when moving from Gitaly to Gitaly Cluster', :requires_praefect, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347828', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/284645', type: :investigating } do
|
context 'when moving from Gitaly to Gitaly Cluster', :requires_praefect, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347828' do
|
||||||
let(:source_storage) { { type: :gitaly, name: QA::Runtime::Env.non_cluster_repository_storage } }
|
let(:source_storage) { { type: :gitaly, name: QA::Runtime::Env.non_cluster_repository_storage } }
|
||||||
let(:destination_storage) { { type: :praefect, name: QA::Runtime::Env.praefect_repository_storage } }
|
let(:destination_storage) { { type: :praefect, name: QA::Runtime::Env.praefect_repository_storage } }
|
||||||
let(:project) do
|
let(:project) do
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
module QA
|
module QA
|
||||||
RSpec.describe 'Manage' do
|
RSpec.describe 'Manage' do
|
||||||
describe 'Create project badge' do
|
describe 'Create project badge', :reliable do
|
||||||
let(:badge_name) { "project-badge-#{SecureRandom.hex(8)}" }
|
let(:badge_name) { "project-badge-#{SecureRandom.hex(8)}" }
|
||||||
let(:expected_badge_link_url) { "#{Runtime::Scenario.gitlab_address}/#{project.path_with_namespace}" }
|
let(:expected_badge_link_url) { "#{Runtime::Scenario.gitlab_address}/#{project.path_with_namespace}" }
|
||||||
let(:expected_badge_image_url) { "#{Runtime::Scenario.gitlab_address}/#{project.path_with_namespace}/badges/main/pipeline.svg" }
|
let(:expected_badge_image_url) { "#{Runtime::Scenario.gitlab_address}/#{project.path_with_namespace}/badges/main/pipeline.svg" }
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
module QA
|
module QA
|
||||||
RSpec.describe 'Manage' do
|
RSpec.describe 'Manage' do
|
||||||
describe 'Personal project permissions' do
|
describe 'Personal project permissions', :reliable do
|
||||||
let!(:owner) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) }
|
let!(:owner) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) }
|
||||||
|
|
||||||
let!(:owner_api_client) { Runtime::API::Client.new(:gitlab, user: owner) }
|
let!(:owner_api_client) { Runtime::API::Client.new(:gitlab, user: owner) }
|
||||||
|
|
|
@ -135,6 +135,16 @@ RSpec.describe GraphqlController do
|
||||||
post :execute
|
post :execute
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'calls the track gitlab cli when trackable method' do
|
||||||
|
agent = 'GLab - GitLab CLI'
|
||||||
|
request.env['HTTP_USER_AGENT'] = agent
|
||||||
|
|
||||||
|
expect(Gitlab::UsageDataCounters::GitLabCliActivityUniqueCounter)
|
||||||
|
.to receive(:track_api_request_when_trackable).with(user_agent: agent, user: user)
|
||||||
|
|
||||||
|
post :execute
|
||||||
|
end
|
||||||
|
|
||||||
it "assigns username in ApplicationContext" do
|
it "assigns username in ApplicationContext" do
|
||||||
post :execute
|
post :execute
|
||||||
|
|
||||||
|
@ -220,6 +230,16 @@ RSpec.describe GraphqlController do
|
||||||
|
|
||||||
subject
|
subject
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'calls the track gitlab cli when trackable method' do
|
||||||
|
agent = 'GLab - GitLab CLI'
|
||||||
|
request.env['HTTP_USER_AGENT'] = agent
|
||||||
|
|
||||||
|
expect(Gitlab::UsageDataCounters::GitLabCliActivityUniqueCounter)
|
||||||
|
.to receive(:track_api_request_when_trackable).with(user_agent: agent, user: user)
|
||||||
|
|
||||||
|
subject
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when user is not logged in' do
|
context 'when user is not logged in' do
|
||||||
|
|
|
@ -142,11 +142,11 @@ RSpec.describe HelpController do
|
||||||
context 'for Markdown formats' do
|
context 'for Markdown formats' do
|
||||||
subject { get :show, params: { path: path }, format: :md }
|
subject { get :show, params: { path: path }, format: :md }
|
||||||
|
|
||||||
let(:path) { 'ssh/index' }
|
let(:path) { 'user/ssh' }
|
||||||
|
|
||||||
context 'when requested file exists' do
|
context 'when requested file exists' do
|
||||||
before do
|
before do
|
||||||
expect_file_read(File.join(Rails.root, 'doc/ssh/index.md'), content: fixture_file('blockquote_fence_after.md'))
|
expect_file_read(File.join(Rails.root, 'doc/user/ssh.md'), content: fixture_file('blockquote_fence_after.md'))
|
||||||
|
|
||||||
subject
|
subject
|
||||||
end
|
end
|
||||||
|
@ -257,7 +257,7 @@ RSpec.describe HelpController do
|
||||||
it 'always renders not found' do
|
it 'always renders not found' do
|
||||||
get :show,
|
get :show,
|
||||||
params: {
|
params: {
|
||||||
path: 'ssh/index'
|
path: 'user/ssh'
|
||||||
},
|
},
|
||||||
format: :foo
|
format: :foo
|
||||||
expect(response).to be_not_found
|
expect(response).to be_not_found
|
||||||
|
|
|
@ -148,6 +148,13 @@ RSpec.describe Projects::IssuesController do
|
||||||
allow(Kaminari.config).to receive(:default_per_page).and_return(1)
|
allow(Kaminari.config).to receive(:default_per_page).and_return(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'redirects to last page when out of bounds on non-html requests' do
|
||||||
|
get :index, params: params.merge(page: last_page + 1), format: 'atom'
|
||||||
|
|
||||||
|
expect(response).to have_gitlab_http_status(:redirect)
|
||||||
|
expect(response).to redirect_to(action: 'index', format: 'atom', page: last_page, state: 'opened')
|
||||||
|
end
|
||||||
|
|
||||||
it 'does not use pagination if disabled' do
|
it 'does not use pagination if disabled' do
|
||||||
allow(controller).to receive(:pagination_disabled?).and_return(true)
|
allow(controller).to receive(:pagination_disabled?).and_return(true)
|
||||||
|
|
||||||
|
|
|
@ -95,8 +95,6 @@ RSpec.describe Releases::GroupReleasesFinder do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'with subgroups' do
|
describe 'with subgroups' do
|
||||||
let(:params) { { include_subgroups: true } }
|
|
||||||
|
|
||||||
subject(:releases) { described_class.new(group, user, params).execute(**args) }
|
subject(:releases) { described_class.new(group, user, params).execute(**args) }
|
||||||
|
|
||||||
context 'with a single-level subgroup' do
|
context 'with a single-level subgroup' do
|
||||||
|
@ -164,22 +162,12 @@ RSpec.describe Releases::GroupReleasesFinder do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the user a guest on the group' do
|
|
||||||
before do
|
|
||||||
group.add_guest(user)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns all releases' do
|
|
||||||
expect(releases).to match_array([v1_1_1, v1_1_0, v6, v1_0_0, p3])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'performance testing' do
|
context 'performance testing' do
|
||||||
shared_examples 'avoids N+1 queries' do |query_params = {}|
|
shared_examples 'avoids N+1 queries' do |query_params = {}|
|
||||||
context 'with subgroups' do
|
context 'with subgroups' do
|
||||||
let(:params) { query_params }
|
let(:params) { query_params }
|
||||||
|
|
||||||
it 'include_subgroups avoids N+1 queries' do
|
it 'subgroups avoids N+1 queries' do
|
||||||
control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
|
control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
|
||||||
releases
|
releases
|
||||||
end.count
|
end.count
|
||||||
|
@ -196,7 +184,6 @@ RSpec.describe Releases::GroupReleasesFinder do
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'avoids N+1 queries'
|
it_behaves_like 'avoids N+1 queries'
|
||||||
it_behaves_like 'avoids N+1 queries', { simple: true }
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -296,5 +296,13 @@ describe('NoteHeader component', () => {
|
||||||
createComponent({ isConfidential: status });
|
createComponent({ isConfidential: status });
|
||||||
expect(findConfidentialIndicator().exists()).toBe(status);
|
expect(findConfidentialIndicator().exists()).toBe(status);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('shows confidential indicator tooltip for project context', () => {
|
||||||
|
createComponent({ isConfidential: true, noteableType: 'issue' });
|
||||||
|
|
||||||
|
expect(findConfidentialIndicator().attributes('title')).toBe(
|
||||||
|
'This comment is confidential and only visible to project members',
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,6 +11,7 @@ import NoteBody from '~/notes/components/note_body.vue';
|
||||||
import NoteHeader from '~/notes/components/note_header.vue';
|
import NoteHeader from '~/notes/components/note_header.vue';
|
||||||
import issueNote from '~/notes/components/noteable_note.vue';
|
import issueNote from '~/notes/components/noteable_note.vue';
|
||||||
import NotesModule from '~/notes/stores/modules';
|
import NotesModule from '~/notes/stores/modules';
|
||||||
|
import { NOTEABLE_TYPE_MAPPING } from '~/notes/constants';
|
||||||
|
|
||||||
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
|
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
|
||||||
|
|
||||||
|
@ -226,6 +227,7 @@ describe('issue_note', () => {
|
||||||
expect(noteHeaderProps.author).toBe(note.author);
|
expect(noteHeaderProps.author).toBe(note.author);
|
||||||
expect(noteHeaderProps.createdAt).toBe(note.created_at);
|
expect(noteHeaderProps.createdAt).toBe(note.created_at);
|
||||||
expect(noteHeaderProps.noteId).toBe(note.id);
|
expect(noteHeaderProps.noteId).toBe(note.id);
|
||||||
|
expect(noteHeaderProps.noteableType).toBe(NOTEABLE_TYPE_MAPPING[note.noteable_type]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render note actions', () => {
|
it('should render note actions', () => {
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe Gitlab::UsageDataCounters::GitLabCliActivityUniqueCounter, :clean_gitlab_redis_shared_state do # rubocop:disable RSpec/FilePath
|
||||||
|
let(:user1) { build(:user, id: 1) }
|
||||||
|
let(:user2) { build(:user, id: 2) }
|
||||||
|
let(:time) { Time.current }
|
||||||
|
let(:action) { described_class::GITLAB_CLI_API_REQUEST_ACTION }
|
||||||
|
let(:user_agent) { { user_agent: 'GLab - GitLab CLI' } }
|
||||||
|
|
||||||
|
context 'when tracking a gitlab cli request' do
|
||||||
|
it_behaves_like 'a request from an extension'
|
||||||
|
end
|
||||||
|
end
|
|
@ -28,7 +28,7 @@ require (
|
||||||
github.com/sirupsen/logrus v1.8.1
|
github.com/sirupsen/logrus v1.8.1
|
||||||
github.com/smartystreets/goconvey v1.6.4
|
github.com/smartystreets/goconvey v1.6.4
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
gitlab.com/gitlab-org/gitaly/v14 v14.9.0-rc1
|
gitlab.com/gitlab-org/gitaly/v14 v14.9.0-rc5.0.20220329111719-51da8bc17059
|
||||||
gitlab.com/gitlab-org/golang-archive-zip v0.1.1
|
gitlab.com/gitlab-org/golang-archive-zip v0.1.1
|
||||||
gitlab.com/gitlab-org/labkit v1.6.0
|
gitlab.com/gitlab-org/labkit v1.6.0
|
||||||
gocloud.dev v0.23.0
|
gocloud.dev v0.23.0
|
||||||
|
|
|
@ -606,7 +606,7 @@ github.com/lib/pq v1.10.1/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/libgit2/git2go v0.0.0-20190104134018-ecaeb7a21d47/go.mod h1:4bKN42efkbNYMZlvDfxGDxzl066GhpvIircZDsm8Y+Y=
|
github.com/libgit2/git2go v0.0.0-20190104134018-ecaeb7a21d47/go.mod h1:4bKN42efkbNYMZlvDfxGDxzl066GhpvIircZDsm8Y+Y=
|
||||||
github.com/libgit2/git2go/v31 v31.4.12/go.mod h1:c/rkJcBcUFx6wHaT++UwNpKvIsmPNqCeQ/vzO4DrEec=
|
github.com/libgit2/git2go/v31 v31.4.12/go.mod h1:c/rkJcBcUFx6wHaT++UwNpKvIsmPNqCeQ/vzO4DrEec=
|
||||||
github.com/libgit2/git2go/v33 v33.0.6/go.mod h1:KdpqkU+6+++4oHna/MIOgx4GCQ92IPCdpVRMRI80J+4=
|
github.com/libgit2/git2go/v33 v33.0.9/go.mod h1:KdpqkU+6+++4oHna/MIOgx4GCQ92IPCdpVRMRI80J+4=
|
||||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20200305213919-a88bf8de3718/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20200305213919-a88bf8de3718/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20210210170715-a8dfcb80d3a7 h1:YjW+hUb8Fh2S58z4av4t/0cBMK/Q0aP48RocCFsC8yI=
|
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20210210170715-a8dfcb80d3a7 h1:YjW+hUb8Fh2S58z4av4t/0cBMK/Q0aP48RocCFsC8yI=
|
||||||
|
@ -886,8 +886,8 @@ github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wK
|
||||||
gitlab.com/gitlab-org/gitaly v1.68.0 h1:VlcJs1+PrhW7lqJUU7Fh1q8FMJujmbbivdfde/cwB98=
|
gitlab.com/gitlab-org/gitaly v1.68.0 h1:VlcJs1+PrhW7lqJUU7Fh1q8FMJujmbbivdfde/cwB98=
|
||||||
gitlab.com/gitlab-org/gitaly v1.68.0/go.mod h1:/pCsB918Zu5wFchZ9hLYin9WkJ2yQqdVNz0zlv5HbXg=
|
gitlab.com/gitlab-org/gitaly v1.68.0/go.mod h1:/pCsB918Zu5wFchZ9hLYin9WkJ2yQqdVNz0zlv5HbXg=
|
||||||
gitlab.com/gitlab-org/gitaly/v14 v14.0.0-rc1/go.mod h1:4Cz8tOAyueSZX5o6gYum1F/unupaOclxqETPcg4ODvQ=
|
gitlab.com/gitlab-org/gitaly/v14 v14.0.0-rc1/go.mod h1:4Cz8tOAyueSZX5o6gYum1F/unupaOclxqETPcg4ODvQ=
|
||||||
gitlab.com/gitlab-org/gitaly/v14 v14.9.0-rc1 h1:9vStRdXxcBQ8dHlVnpV28fwLOgyDkSFIpGnPqwzdTvw=
|
gitlab.com/gitlab-org/gitaly/v14 v14.9.0-rc5.0.20220329111719-51da8bc17059 h1:X7+3GQIxUpScXpIMCU5+sfpYvZyBIQ3GMlEosP7Jssw=
|
||||||
gitlab.com/gitlab-org/gitaly/v14 v14.9.0-rc1/go.mod h1:Xk5pn6IWsejg3z2X6BRczC5QaI97PRF3GU5OrJ5Amkg=
|
gitlab.com/gitlab-org/gitaly/v14 v14.9.0-rc5.0.20220329111719-51da8bc17059/go.mod h1:uX1qhFKBDuPqATlpMcFL2dKDiX8D/tbUg7CYWx7OXt4=
|
||||||
gitlab.com/gitlab-org/gitlab-shell v1.9.8-0.20201117050822-3f9890ef73dc/go.mod h1:5QSTbpAHY2v0iIH5uHh2KA9w7sPUqPmnLjDApI/sv1U=
|
gitlab.com/gitlab-org/gitlab-shell v1.9.8-0.20201117050822-3f9890ef73dc/go.mod h1:5QSTbpAHY2v0iIH5uHh2KA9w7sPUqPmnLjDApI/sv1U=
|
||||||
gitlab.com/gitlab-org/gitlab-shell v1.9.8-0.20210720163109-50da611814d2/go.mod h1:QWDYBwuy24qGMandtCngLRPzFgnGPg6LSNoJWPKmJMc=
|
gitlab.com/gitlab-org/gitlab-shell v1.9.8-0.20210720163109-50da611814d2/go.mod h1:QWDYBwuy24qGMandtCngLRPzFgnGPg6LSNoJWPKmJMc=
|
||||||
gitlab.com/gitlab-org/golang-archive-zip v0.1.1 h1:35k9giivbxwF03+8A05Cm8YoxoakU8FBCj5gysjCTCE=
|
gitlab.com/gitlab-org/golang-archive-zip v0.1.1 h1:35k9giivbxwF03+8A05Cm8YoxoakU8FBCj5gysjCTCE=
|
||||||
|
|
Loading…
Reference in New Issue