Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
4badf32da7
commit
4d1b4c1cf3
|
|
@ -1003,7 +1003,6 @@ Layout/LineLength:
|
|||
- 'ee/spec/features/projects_spec.rb'
|
||||
- 'ee/spec/features/promotion_spec.rb'
|
||||
- 'ee/spec/features/read_only_spec.rb'
|
||||
- 'ee/spec/features/search/elastic/snippet_search_spec.rb'
|
||||
- 'ee/spec/features/users/login_spec.rb'
|
||||
- 'ee/spec/finders/analytics/devops_adoption/enabled_namespaces_finder_spec.rb'
|
||||
- 'ee/spec/finders/analytics/devops_adoption/snapshots_finder_spec.rb'
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ export default {
|
|||
<template>
|
||||
<div class="gl-p-4">
|
||||
<div class="gl-flex" dir="auto">
|
||||
<h4
|
||||
<h3
|
||||
class="board-card-title gl-isolate gl-mb-0 gl-mt-0 gl-min-w-0 gl-hyphens-auto gl-break-words gl-text-base"
|
||||
:class="{ 'gl-mr-6': hasActions }"
|
||||
>
|
||||
|
|
@ -294,7 +294,7 @@ export default {
|
|||
@click.prevent
|
||||
>{{ item.title }}</a
|
||||
>
|
||||
</h4>
|
||||
</h3>
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div v-if="showLabelFooter" class="board-card-labels gl-mt-2 gl-flex gl-flex-wrap">
|
||||
|
|
|
|||
|
|
@ -811,22 +811,20 @@ export default {
|
|||
@appear="onReachingListBottom"
|
||||
/>
|
||||
</board-card>
|
||||
<div>
|
||||
<!-- for supporting previous structure with intersection observer -->
|
||||
<li
|
||||
v-if="showCount"
|
||||
class="board-list-count gl-py-4 gl-text-center gl-text-subtle"
|
||||
data-issue-id="-1"
|
||||
>
|
||||
<gl-loading-icon
|
||||
v-if="isLoadingMore"
|
||||
size="sm"
|
||||
:label="$options.i18n.loadingMoreBoardItems"
|
||||
/>
|
||||
<span v-if="showingAllItems">{{ showingAllItemsText }}</span>
|
||||
<span v-else>{{ paginatedIssueText }}</span>
|
||||
</li>
|
||||
</div>
|
||||
<!-- for supporting previous structure with intersection observer -->
|
||||
<li
|
||||
v-if="showCount"
|
||||
class="board-list-count gl-py-4 gl-text-center gl-text-subtle"
|
||||
data-issue-id="-1"
|
||||
>
|
||||
<gl-loading-icon
|
||||
v-if="isLoadingMore"
|
||||
size="sm"
|
||||
:label="$options.i18n.loadingMoreBoardItems"
|
||||
/>
|
||||
<span v-if="showingAllItems">{{ showingAllItemsText }}</span>
|
||||
<span v-else>{{ paginatedIssueText }}</span>
|
||||
</li>
|
||||
</component>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -336,7 +336,7 @@ export default {
|
|||
class="board-header gl-relative"
|
||||
data-testid="board-list-header"
|
||||
>
|
||||
<h3
|
||||
<div
|
||||
:class="{
|
||||
'gl-cursor-grab': userCanDrag,
|
||||
'gl-h-full gl-py-3': list.collapsed && !isSwimlanesHeader,
|
||||
|
|
@ -399,8 +399,8 @@ export default {
|
|||
:style="{ color: listStatusColor }"
|
||||
/>
|
||||
<!-- EE end -->
|
||||
<div
|
||||
class="board-title-text"
|
||||
<h2
|
||||
class="gl-text-bold board-title-text gl-text-base"
|
||||
:class="{
|
||||
'gl-hidden': list.collapsed && isSwimlanesHeader,
|
||||
'gl-mx-0 gl-my-3 gl-flex-grow-0 gl-rotate-90 gl-py-0': list.collapsed,
|
||||
|
|
@ -438,7 +438,7 @@ export default {
|
|||
:scoped="showScopedLabels(list.label)"
|
||||
:title="list.label.title"
|
||||
/>
|
||||
</div>
|
||||
</h2>
|
||||
|
||||
<!-- EE start -->
|
||||
<span
|
||||
|
|
@ -553,6 +553,6 @@ export default {
|
|||
@click="openSidebarSettings"
|
||||
/>
|
||||
</gl-button-group>
|
||||
</h3>
|
||||
</div>
|
||||
</header>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,78 @@
|
|||
<script>
|
||||
import { computed } from 'vue';
|
||||
import { GlButton, GlTooltipDirective } from '@gitlab/ui';
|
||||
import { TABS_INDICES } from '~/todos/constants';
|
||||
import TodoItem from '~/todos/components/todo_item.vue';
|
||||
import getTodosQuery from '~/todos/components/queries/get_todos.query.graphql';
|
||||
import * as Sentry from '~/sentry/sentry_browser_wrapper';
|
||||
|
||||
const N_TODOS = 5;
|
||||
|
||||
export default {
|
||||
components: {},
|
||||
components: { TodoItem, GlButton },
|
||||
directives: {
|
||||
GlTooltip: GlTooltipDirective,
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
currentTab: TABS_INDICES.pending,
|
||||
currentTime: new Date(),
|
||||
currentUserId: computed(() => this.currentUserId),
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentUserId: null,
|
||||
todos: [],
|
||||
};
|
||||
},
|
||||
apollo: {
|
||||
todos: {
|
||||
query: getTodosQuery,
|
||||
variables() {
|
||||
return {
|
||||
first: N_TODOS,
|
||||
state: ['pending'],
|
||||
};
|
||||
},
|
||||
update({ currentUser: { id, todos: { nodes = [] } } = {} }) {
|
||||
this.currentUserId = id;
|
||||
|
||||
return nodes;
|
||||
},
|
||||
error(error) {
|
||||
Sentry.captureException(error);
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h4>{{ __('Latest to-do items') }}</h4>
|
||||
<div class="gl-flex gl-items-center gl-justify-between gl-gap-2">
|
||||
<h4>{{ __('Latest to-do items') }}</h4>
|
||||
|
||||
<gl-button
|
||||
v-gl-tooltip.hover
|
||||
icon="retry"
|
||||
:aria-label="__('Refresh')"
|
||||
:title="__('Refresh')"
|
||||
:loading="$apollo.queries.todos.loading"
|
||||
category="tertiary"
|
||||
size="small"
|
||||
@click="$apollo.queries.todos.refetch()"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<todo-item
|
||||
v-for="todo in todos"
|
||||
:key="todo.id"
|
||||
:todo="todo"
|
||||
@change="$apollo.queries.todos.refetch()"
|
||||
/>
|
||||
<div class="gl-p-3">
|
||||
<a href="/dashboard/todos">{{ __('All to-do items') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -3,9 +3,15 @@
|
|||
// of a dashboard controller. The root index redirects for all other default dashboards.
|
||||
import '../dashboard/projects/index';
|
||||
|
||||
const isNewHomepage = gon.features.personalHomepage;
|
||||
|
||||
// With the new `personal_homepage` feature flag enabled, the root_url now renders a different page.
|
||||
// We can keep above import for now. It is still required for when the feature flag is disabled for
|
||||
// a user.
|
||||
import initHomepage from '~/homepage/index';
|
||||
|
||||
initHomepage();
|
||||
(async () => {
|
||||
if (isNewHomepage) {
|
||||
const { default: initHomepage } = await import('~/homepage/index');
|
||||
initHomepage();
|
||||
}
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
<script>
|
||||
import Vue from 'vue';
|
||||
import { GlFormCheckboxGroup, GlFormCheckbox } from '@gitlab/ui';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { mapActions, mapGetters } from 'vuex';
|
||||
|
|
@ -44,8 +43,9 @@ export default {
|
|||
async set(value) {
|
||||
this.setQuery({ key: this.queryParam, value });
|
||||
|
||||
await Vue.nextTick();
|
||||
this.trackSelectCheckbox();
|
||||
this.$nextTick(() => {
|
||||
this.trackSelectCheckbox();
|
||||
});
|
||||
},
|
||||
},
|
||||
labelCountClasses() {
|
||||
|
|
|
|||
|
|
@ -24,14 +24,15 @@ export default {
|
|||
},
|
||||
inject: ['currentTab'],
|
||||
props: {
|
||||
currentUserId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
todo: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
selectable: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
selected: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
|
|
@ -73,6 +74,7 @@ export default {
|
|||
:class="{ 'gl-bg-subtle': isDone }"
|
||||
>
|
||||
<gl-form-checkbox
|
||||
v-if="selectable"
|
||||
class="gl-inline-block gl-pt-2"
|
||||
:aria-label="__('Select')"
|
||||
:checked="selected"
|
||||
|
|
@ -93,11 +95,7 @@ export default {
|
|||
:todo="todo"
|
||||
class="gl-flex gl-items-center gl-gap-2 gl-overflow-hidden gl-whitespace-nowrap gl-px-2 gl-pb-3 gl-pt-2 gl-text-sm gl-text-subtle sm:gl-mr-0 sm:gl-pr-4 md:gl-mb-1"
|
||||
/>
|
||||
<todo-item-body
|
||||
:todo="todo"
|
||||
:current-user-id="currentUserId"
|
||||
:is-hidden-by-saml="isHiddenBySaml"
|
||||
/>
|
||||
<todo-item-body :todo="todo" :is-hidden-by-saml="isHiddenBySaml" />
|
||||
</div>
|
||||
|
||||
<todo-snoozed-timestamp
|
||||
|
|
|
|||
|
|
@ -31,11 +31,8 @@ export default {
|
|||
directives: {
|
||||
SafeHtml,
|
||||
},
|
||||
inject: ['currentUserId'],
|
||||
props: {
|
||||
currentUserId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
todo: {
|
||||
type: Object,
|
||||
required: true,
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ export default {
|
|||
return {
|
||||
currentTab: computed(() => this.currentTab),
|
||||
currentTime: computed(() => this.currentTime),
|
||||
currentUserId: computed(() => this.currentUserId),
|
||||
};
|
||||
},
|
||||
data() {
|
||||
|
|
@ -425,7 +426,7 @@ export default {
|
|||
v-for="todo in todos"
|
||||
:key="todo.id"
|
||||
:todo="todo"
|
||||
:current-user-id="currentUserId"
|
||||
selectable
|
||||
:selected="selectedIds.includes(todo.id)"
|
||||
@change="handleItemChanged"
|
||||
@select-change="handleSelectionChanged"
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ $diff-file-header: 41px;
|
|||
.diff-file {
|
||||
margin-bottom: $gl-padding;
|
||||
|
||||
table.code tr:last-of-type td:last-of-type {
|
||||
border-bottom-left-radius: $gl-border-radius-lg-inner;
|
||||
border-bottom-right-radius: $gl-border-radius-lg-inner;
|
||||
.code.md-suggestion-diff {
|
||||
border-bottom-left-radius: $gl-border-radius-base-inner;
|
||||
border-bottom-right-radius: $gl-border-radius-base-inner;
|
||||
}
|
||||
|
||||
.file-title,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
- if visible?
|
||||
%td.rd-line-number{ id: id, class: border_class, data: { legacy_id: legacy_id, change: change_type, position: @position } }
|
||||
%td.rd-line-number{ id: id, class: border_class, data: { change: change_type, position: @position } }
|
||||
= link_to '', "##{id}", { class: 'rd-line-link', data: { line_number: line_number }, aria: { label: label } }
|
||||
- else
|
||||
%td.rd-line-number{ class: border_class, data: { change: change_type, position: @position } }
|
||||
|
|
|
|||
|
|
@ -20,10 +20,6 @@ module RapidDiffs
|
|||
@position == :old ? @line.old_pos : @line.new_pos
|
||||
end
|
||||
|
||||
def legacy_id
|
||||
@line.legacy_id(@file_path)
|
||||
end
|
||||
|
||||
def change_type
|
||||
return unless @line
|
||||
return 'meta' if @line.meta?
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@ class RootController < Dashboard::ProjectsController
|
|||
before_action :redirect_unlogged_user, if: -> { current_user.nil? }
|
||||
before_action :redirect_logged_user, if: -> { current_user.present? }
|
||||
|
||||
before_action only: [:index] do
|
||||
push_frontend_feature_flag(:personal_homepage, current_user)
|
||||
end
|
||||
|
||||
CACHE_CONTROL_HEADER = 'no-store'
|
||||
|
||||
def index
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ module MergeRequests
|
|||
merge_after: [:merge_schedule],
|
||||
mergeable: [:merge_schedule],
|
||||
detailed_merge_status: [:merge_schedule],
|
||||
milestone: [:milestone],
|
||||
mergeability_checks: [:merge_schedule, :unresolved_notes, { target_project: [:lfs_file_locks] }],
|
||||
milestone: [:milestone, { milestone: [:project, :group] }],
|
||||
security_auto_fix: [:author],
|
||||
head_pipeline: [:merge_request_diff, { head_pipeline: [:merge_request, :project] }],
|
||||
timelogs: [:timelogs],
|
||||
|
|
@ -38,7 +39,8 @@ module MergeRequests
|
|||
suggested_reviewers: [:predictions],
|
||||
diff_stats: [latest_merge_request_diff: [:merge_request_diff_commits]],
|
||||
source_branch_exists: [:source_project, { source_project: [:route] }],
|
||||
squash_read_only: { target_project: :project_setting }
|
||||
squash_read_only: { target_project: :project_setting },
|
||||
web_url: { target_project: [:route, { namespace: [:route] }] }
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ module DiffHelper
|
|||
end
|
||||
|
||||
def file_heading_id(diff_file)
|
||||
"#{diff_file.file_hash}-heading"
|
||||
"#{diff_file.file_hash[0..8]}-heading"
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ class ProjectCiCdSetting < ApplicationRecord
|
|||
include ChronicDurationAttribute
|
||||
include EachBatch
|
||||
|
||||
ignore_column :restrict_user_defined_variables, remove_with: '18.3', remove_after: '2025-08-14'
|
||||
|
||||
belongs_to :project, inverse_of: :ci_cd_settings
|
||||
|
||||
DEFAULT_GIT_DEPTH = 20
|
||||
|
|
@ -101,24 +103,9 @@ class ProjectCiCdSetting < ApplicationRecord
|
|||
role_access_level >= role_project_minimum_access_level || user&.can_admin_all_resources?
|
||||
end
|
||||
|
||||
def pipeline_variables_minimum_override_role=(value)
|
||||
return if value.nil?
|
||||
|
||||
self[:restrict_user_defined_variables] = true # don't use the method because it's overridden
|
||||
self[:pipeline_variables_minimum_override_role] = value
|
||||
end
|
||||
|
||||
def pipeline_variables_minimum_override_role
|
||||
return 'developer' unless restrict_user_defined_variables
|
||||
|
||||
self[:pipeline_variables_minimum_override_role]
|
||||
end
|
||||
|
||||
def restrict_user_defined_variables=(value)
|
||||
return unless [true, false].include?(value)
|
||||
|
||||
self[:restrict_user_defined_variables] = true
|
||||
|
||||
if value == true && pipeline_variables_minimum_override_role == 'developer'
|
||||
self[:pipeline_variables_minimum_override_role] = 'maintainer'
|
||||
elsif value == true && pipeline_variables_minimum_override_role != 'developer'
|
||||
|
|
@ -128,14 +115,13 @@ class ProjectCiCdSetting < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def restrict_user_defined_variables
|
||||
self[:restrict_user_defined_variables] && self[:pipeline_variables_minimum_override_role] != 'developer'
|
||||
def restrict_user_defined_variables?
|
||||
self[:pipeline_variables_minimum_override_role] != 'developer'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_pipeline_variables_secure_defaults
|
||||
self.restrict_user_defined_variables = true
|
||||
self.pipeline_variables_minimum_override_role = project.root_namespace.pipeline_variables_default_role
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -42,12 +42,21 @@ module MergeRequests
|
|||
format(CACHE_KEY, id: id, sha: sha, epoch: epoch)
|
||||
end
|
||||
|
||||
def has_lfs_file_locks?
|
||||
if project.lfs_file_locks.loaded?
|
||||
project.lfs_file_locks.any?
|
||||
else
|
||||
project.lfs_file_locks.exists?
|
||||
end
|
||||
end
|
||||
strong_memoize_attr :has_lfs_file_locks?
|
||||
|
||||
private
|
||||
|
||||
delegate :project, :author_id, :changed_paths, to: :merge_request
|
||||
|
||||
def contains_locked_lfs_files?
|
||||
return false unless project.lfs_file_locks.exists?
|
||||
return false unless has_lfs_file_locks?
|
||||
|
||||
paths = changed_paths.map(&:path).uniq
|
||||
project.lfs_file_locks.for_paths(paths).not_for_users(author_id).exists?
|
||||
|
|
|
|||
|
|
@ -103,13 +103,6 @@ module Projects
|
|||
raise_api_error(s_("UpdateProject|Changing the ci_pipeline_variables_minimum_override_role to the owner role is not allowed"))
|
||||
end
|
||||
|
||||
# If this is disabled via API we want to ensure we convert to the backwards compatible minimum
|
||||
# override role 'developer'. We want to keep this attribute always "true" until removal.
|
||||
if params[:restrict_user_defined_variables] == false
|
||||
params[:restrict_user_defined_variables] = true
|
||||
params[:ci_pipeline_variables_minimum_override_role] = 'developer'
|
||||
end
|
||||
|
||||
return if can?(current_user, :change_restrict_user_defined_variables, project)
|
||||
|
||||
raise_api_error(s_("UpdateProject|Changing the restrict_user_defined_variables or ci_pipeline_variables_minimum_override_role is not allowed"))
|
||||
|
|
@ -265,7 +258,7 @@ module Projects
|
|||
new_restrict_user_defined_variables = params[:restrict_user_defined_variables]
|
||||
return false if new_restrict_user_defined_variables.nil?
|
||||
|
||||
project.restrict_user_defined_variables != new_restrict_user_defined_variables
|
||||
project.restrict_user_defined_variables? != new_restrict_user_defined_variables
|
||||
end
|
||||
|
||||
def changing_pipeline_variables_minimum_override_role?
|
||||
|
|
|
|||
|
|
@ -4,10 +4,13 @@
|
|||
- @content_wrapper_class = "#{@content_wrapper_class} gl-relative gl-pb-0"
|
||||
- @content_class = "issue-boards-content js-focus-mode-board"
|
||||
- is_epic_board = board.to_type == "EpicBoard"
|
||||
- if is_epic_board
|
||||
- breadcrumb_title _("Epic Boards")
|
||||
- else
|
||||
- breadcrumb_title _("Issue Boards")
|
||||
- title = is_epic_board ? _("Epic Boards") : _("Issue Boards")
|
||||
- page_title title
|
||||
- breadcrumb_title title
|
||||
|
||||
%h1.gl-sr-only= title
|
||||
|
||||
- if !is_epic_board
|
||||
= render 'shared/alerts/positioning_disabled'
|
||||
|
||||
= content_for :after_content do
|
||||
|
|
|
|||
|
|
@ -306,11 +306,6 @@ These known issues reflect only the latest version of GitLab. If you are using a
|
|||
- When a [secondary site uses a separate URL](secondary_proxy/_index.md#set-up-a-separate-url-for-a-secondary-geo-site) from the primary site, [signing in the secondary site using SAML](replication/single_sign_on.md#saml-with-separate-url-with-proxying-enabled) is only supported if the SAML Identity Provider (IdP) allows an application to be configured with multiple callback URLs.
|
||||
- Git clone and fetch requests with option `--depth` over SSH against a secondary site does not work and hangs indefinitely if the secondary site is not up to date at the time the request is initiated. This is due to problems related to translating Git SSH to Git https during proxying. For more information, see [issue 391980](https://gitlab.com/gitlab-org/gitlab/-/issues/391980). A new workflow that does not involve the aforementioned translation step is now available for Linux-packaged GitLab Geo secondary sites which can be enabled with a feature flag. For more details, see [comment in issue 454707](https://gitlab.com/gitlab-org/gitlab/-/issues/454707#note_2102067451). The fix for Cloud Native GitLab Geo secondary sites is tracked in [issue 5641](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/5641).
|
||||
- Some customers have reported that `git fetch` over SSH when the secondary site is out of date hangs and/or times out and fails. `git clone` requests over SSH are not impacted. For more information, see [issue 454707](https://gitlab.com/gitlab-org/gitlab/-/issues/454707). A fix available for Linux-packaged GitLab Geo secondary sites which can be enabled with a feature flag. For more details, see [comment in issue 454707](https://gitlab.com/gitlab-org/gitlab/-/issues/454707#note_2102067451). The fix for Cloud Native GitLab Geo secondary sites is tracked in [issue 5641](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/5641).
|
||||
- When the site name is configured to match the external URL, it is important to ensure
|
||||
that you add the trailing slash of the URL to the `gitlab_rails['geo_node_name']`
|
||||
definition in `/etc/gitlab/gitlab.rb`. Otherwise, it can cause the site to be
|
||||
misconfigured after updating the site's data from the Admin page.
|
||||
For more information, see [issue 536444](https://gitlab.com/gitlab-org/gitlab/-/issues/536444).
|
||||
|
||||
### Replicated data types
|
||||
|
||||
|
|
|
|||
|
|
@ -226,16 +226,6 @@ In the following steps, replace `<ssh_host_key_path>` with the one you're using:
|
|||
gitlab_rails['geo_node_name'] = '<site_name_here>'
|
||||
```
|
||||
|
||||
{{< alert type="warning" >}}
|
||||
|
||||
When the site name is configured to match the external URL, it is important to ensure
|
||||
that you add the trailing slash of the URL to the `gitlab_rails['geo_node_name']`
|
||||
definition in `/etc/gitlab/gitlab.rb`. Otherwise, it can cause the site to be
|
||||
misconfigured after updating the site's data from the Admin page.
|
||||
For more information, see [issue 536444](https://gitlab.com/gitlab-org/gitlab/-/issues/536444).
|
||||
|
||||
{{< /alert >}}
|
||||
|
||||
1. Reconfigure **each Rails and Sidekiq node on your secondary** site for the change to take effect:
|
||||
|
||||
```shell
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ title: Migrate epic APIs to work items
|
|||
- Listing epics using the [GraphQL API](reference/_index.md) [introduced](https://gitlab.com/groups/gitlab-org/-/epics/12852) in GitLab 17.4.
|
||||
- [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/470685) in GitLab 17.6.
|
||||
- [Enabled by default on GitLab Self-Managed and GitLab Dedicated](https://gitlab.com/gitlab-org/gitlab/-/issues/468310) in GitLab 17.7.
|
||||
- [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/468310) in GitLab 18.1.
|
||||
|
||||
{{< /history >}}
|
||||
|
||||
|
|
|
|||
|
|
@ -1649,7 +1649,7 @@ four standard [pagination arguments](#pagination-arguments):
|
|||
| <a id="queryvulnerabilitieshasresolution"></a>`hasResolution` | [`Boolean`](#boolean) | Returns only the vulnerabilities which have been resolved on default branch. |
|
||||
| <a id="queryvulnerabilitiesidentifiername"></a>`identifierName` | [`String`](#string) | Filter vulnerabilities by identifier name. Ignored when applied on instance security dashboard queries. |
|
||||
| <a id="queryvulnerabilitiesimage"></a>`image` | [`[String!]`](#string) | Filter vulnerabilities by location image. When this filter is present, the response only matches entries for a `reportType` that includes `container_scanning`, `cluster_image_scanning`. |
|
||||
| <a id="queryvulnerabilitiesowasptopten"></a>`owaspTopTen` | [`[VulnerabilityOwaspTop10!]`](#vulnerabilityowasptop10) | Filter vulnerabilities by OWASP Top 10 category. Wildcard value `NONE` is also supported but it cannot be combined with other OWASP top 10 values. Experimental support for OWASP 2021 values is deprecated and the removal is tracked in <https://gitlab.com/gitlab-org/gitlab/-/issues/539250> Instead, use the `owasp_top_ten_2021` argument to continue filtering by OWASP 2021 values. |
|
||||
| <a id="queryvulnerabilitiesowasptopten"></a>`owaspTopTen` | [`[VulnerabilityOwaspTop10!]`](#vulnerabilityowasptop10) | Filter vulnerabilities by OWASP Top 10 2017 category. Wildcard value `NONE` is also supported but it cannot be combined with other OWASP top 10 values. |
|
||||
| <a id="queryvulnerabilitiesowasptopten2021"></a>`owaspTopTen2021` {{< icon name="warning-solid" >}} | [`[VulnerabilityOwasp2021Top10!]`](#vulnerabilityowasp2021top10) | **Introduced** in GitLab 18.1. **Status**: Experiment. Filter vulnerabilities by OWASP Top 10 2021 category. Wildcard value `NONE` is also supported but it cannot be combined with other OWASP top 10 2021 values. To use this argument, you must have Elasticsearch configured and the `advanced_vulnerability_management` feature flag enabled. Not supported on Instance Security Dashboard queries. |
|
||||
| <a id="queryvulnerabilitiesprojectid"></a>`projectId` | [`[ID!]`](#id) | Filter vulnerabilities by project. |
|
||||
| <a id="queryvulnerabilitiesreporttype"></a>`reportType` | [`[VulnerabilityReportType!]`](#vulnerabilityreporttype) | Filter vulnerabilities by report type. |
|
||||
|
|
@ -29795,7 +29795,7 @@ four standard [pagination arguments](#pagination-arguments):
|
|||
| <a id="groupvulnerabilitieshasresolution"></a>`hasResolution` | [`Boolean`](#boolean) | Returns only the vulnerabilities which have been resolved on default branch. |
|
||||
| <a id="groupvulnerabilitiesidentifiername"></a>`identifierName` | [`String`](#string) | Filter vulnerabilities by identifier name. Ignored when applied on instance security dashboard queries. |
|
||||
| <a id="groupvulnerabilitiesimage"></a>`image` | [`[String!]`](#string) | Filter vulnerabilities by location image. When this filter is present, the response only matches entries for a `reportType` that includes `container_scanning`, `cluster_image_scanning`. |
|
||||
| <a id="groupvulnerabilitiesowasptopten"></a>`owaspTopTen` | [`[VulnerabilityOwaspTop10!]`](#vulnerabilityowasptop10) | Filter vulnerabilities by OWASP Top 10 category. Wildcard value `NONE` is also supported but it cannot be combined with other OWASP top 10 values. Experimental support for OWASP 2021 values is deprecated and the removal is tracked in <https://gitlab.com/gitlab-org/gitlab/-/issues/539250> Instead, use the `owasp_top_ten_2021` argument to continue filtering by OWASP 2021 values. |
|
||||
| <a id="groupvulnerabilitiesowasptopten"></a>`owaspTopTen` | [`[VulnerabilityOwaspTop10!]`](#vulnerabilityowasptop10) | Filter vulnerabilities by OWASP Top 10 2017 category. Wildcard value `NONE` is also supported but it cannot be combined with other OWASP top 10 values. |
|
||||
| <a id="groupvulnerabilitiesowasptopten2021"></a>`owaspTopTen2021` {{< icon name="warning-solid" >}} | [`[VulnerabilityOwasp2021Top10!]`](#vulnerabilityowasp2021top10) | **Introduced** in GitLab 18.1. **Status**: Experiment. Filter vulnerabilities by OWASP Top 10 2021 category. Wildcard value `NONE` is also supported but it cannot be combined with other OWASP top 10 2021 values. To use this argument, you must have Elasticsearch configured and the `advanced_vulnerability_management` feature flag enabled. Not supported on Instance Security Dashboard queries. |
|
||||
| <a id="groupvulnerabilitiesprojectid"></a>`projectId` | [`[ID!]`](#id) | Filter vulnerabilities by project. |
|
||||
| <a id="groupvulnerabilitiesreporttype"></a>`reportType` | [`[VulnerabilityReportType!]`](#vulnerabilityreporttype) | Filter vulnerabilities by report type. |
|
||||
|
|
@ -29889,7 +29889,7 @@ Returns [`VulnerabilitySeveritiesCount`](#vulnerabilityseveritiescount).
|
|||
| <a id="groupvulnerabilityseveritiescounthasresolution"></a>`hasResolution` | [`Boolean`](#boolean) | Filter vulnerabilities that do or do not have a resolution. |
|
||||
| <a id="groupvulnerabilityseveritiescountidentifiername"></a>`identifierName` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Filter vulnerabilities by identifier name. Ignored when applied on instance security dashboard queries. |
|
||||
| <a id="groupvulnerabilityseveritiescountimage"></a>`image` | [`[String!]`](#string) | Filter vulnerabilities by location image. When this filter is present, the response only matches entries for a `reportType` that includes `container_scanning`, `cluster_image_scanning`. |
|
||||
| <a id="groupvulnerabilityseveritiescountowasptopten"></a>`owaspTopTen` | [`[VulnerabilityOwaspTop10!]`](#vulnerabilityowasptop10) | Filter vulnerabilities by OWASP Top 10 category. Wildcard value `NONE` is also supported but it cannot be combined with other OWASP top 10 values. Experimental support for OWASP 2021 values is deprecated and the removal is tracked in <https://gitlab.com/gitlab-org/gitlab/-/issues/539250> Instead, use the `owasp_top_ten_2021` argument to continue filtering by OWASP 2021 values. |
|
||||
| <a id="groupvulnerabilityseveritiescountowasptopten"></a>`owaspTopTen` | [`[VulnerabilityOwaspTop10!]`](#vulnerabilityowasptop10) | Filter vulnerabilities by OWASP Top 10 2017 category. Wildcard value `NONE` is also supported but it cannot be combined with other OWASP top 10 values. |
|
||||
| <a id="groupvulnerabilityseveritiescountowasptopten2021"></a>`owaspTopTen2021` {{< icon name="warning-solid" >}} | [`[VulnerabilityOwasp2021Top10!]`](#vulnerabilityowasp2021top10) | **Introduced** in GitLab 18.1. **Status**: Experiment. Filter vulnerabilities by OWASP Top 10 2021 category. Wildcard value `NONE` is also supported but it cannot be combined with other OWASP top 10 2021 values. To use this argument, you must have Elasticsearch configured and the `advanced_vulnerability_management` feature flag enabled. Not supported on Instance Security Dashboard queries. |
|
||||
| <a id="groupvulnerabilityseveritiescountprojectid"></a>`projectId` | [`[ID!]`](#id) | Filter vulnerabilities by project. |
|
||||
| <a id="groupvulnerabilityseveritiescountreporttype"></a>`reportType` | [`[VulnerabilityReportType!]`](#vulnerabilityreporttype) | Filter vulnerabilities by report type. |
|
||||
|
|
@ -30828,7 +30828,7 @@ Returns [`VulnerabilitySeveritiesCount`](#vulnerabilityseveritiescount).
|
|||
| <a id="instancesecuritydashboardvulnerabilityseveritiescounthasresolution"></a>`hasResolution` | [`Boolean`](#boolean) | Filter vulnerabilities that do or do not have a resolution. |
|
||||
| <a id="instancesecuritydashboardvulnerabilityseveritiescountidentifiername"></a>`identifierName` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Filter vulnerabilities by identifier name. Ignored when applied on instance security dashboard queries. |
|
||||
| <a id="instancesecuritydashboardvulnerabilityseveritiescountimage"></a>`image` | [`[String!]`](#string) | Filter vulnerabilities by location image. When this filter is present, the response only matches entries for a `reportType` that includes `container_scanning`, `cluster_image_scanning`. |
|
||||
| <a id="instancesecuritydashboardvulnerabilityseveritiescountowasptopten"></a>`owaspTopTen` | [`[VulnerabilityOwaspTop10!]`](#vulnerabilityowasptop10) | Filter vulnerabilities by OWASP Top 10 category. Wildcard value `NONE` is also supported but it cannot be combined with other OWASP top 10 values. Experimental support for OWASP 2021 values is deprecated and the removal is tracked in <https://gitlab.com/gitlab-org/gitlab/-/issues/539250> Instead, use the `owasp_top_ten_2021` argument to continue filtering by OWASP 2021 values. |
|
||||
| <a id="instancesecuritydashboardvulnerabilityseveritiescountowasptopten"></a>`owaspTopTen` | [`[VulnerabilityOwaspTop10!]`](#vulnerabilityowasptop10) | Filter vulnerabilities by OWASP Top 10 2017 category. Wildcard value `NONE` is also supported but it cannot be combined with other OWASP top 10 values. |
|
||||
| <a id="instancesecuritydashboardvulnerabilityseveritiescountowasptopten2021"></a>`owaspTopTen2021` {{< icon name="warning-solid" >}} | [`[VulnerabilityOwasp2021Top10!]`](#vulnerabilityowasp2021top10) | **Introduced** in GitLab 18.1. **Status**: Experiment. Filter vulnerabilities by OWASP Top 10 2021 category. Wildcard value `NONE` is also supported but it cannot be combined with other OWASP top 10 2021 values. To use this argument, you must have Elasticsearch configured and the `advanced_vulnerability_management` feature flag enabled. Not supported on Instance Security Dashboard queries. |
|
||||
| <a id="instancesecuritydashboardvulnerabilityseveritiescountprojectid"></a>`projectId` | [`[ID!]`](#id) | Filter vulnerabilities by project. |
|
||||
| <a id="instancesecuritydashboardvulnerabilityseveritiescountreporttype"></a>`reportType` | [`[VulnerabilityReportType!]`](#vulnerabilityreporttype) | Filter vulnerabilities by report type. |
|
||||
|
|
@ -38157,7 +38157,7 @@ four standard [pagination arguments](#pagination-arguments):
|
|||
| <a id="projectvulnerabilitieshasresolution"></a>`hasResolution` | [`Boolean`](#boolean) | Returns only the vulnerabilities which have been resolved on default branch. |
|
||||
| <a id="projectvulnerabilitiesidentifiername"></a>`identifierName` | [`String`](#string) | Filter vulnerabilities by identifier name. Ignored when applied on instance security dashboard queries. |
|
||||
| <a id="projectvulnerabilitiesimage"></a>`image` | [`[String!]`](#string) | Filter vulnerabilities by location image. When this filter is present, the response only matches entries for a `reportType` that includes `container_scanning`, `cluster_image_scanning`. |
|
||||
| <a id="projectvulnerabilitiesowasptopten"></a>`owaspTopTen` | [`[VulnerabilityOwaspTop10!]`](#vulnerabilityowasptop10) | Filter vulnerabilities by OWASP Top 10 category. Wildcard value `NONE` is also supported but it cannot be combined with other OWASP top 10 values. Experimental support for OWASP 2021 values is deprecated and the removal is tracked in <https://gitlab.com/gitlab-org/gitlab/-/issues/539250> Instead, use the `owasp_top_ten_2021` argument to continue filtering by OWASP 2021 values. |
|
||||
| <a id="projectvulnerabilitiesowasptopten"></a>`owaspTopTen` | [`[VulnerabilityOwaspTop10!]`](#vulnerabilityowasptop10) | Filter vulnerabilities by OWASP Top 10 2017 category. Wildcard value `NONE` is also supported but it cannot be combined with other OWASP top 10 values. |
|
||||
| <a id="projectvulnerabilitiesowasptopten2021"></a>`owaspTopTen2021` {{< icon name="warning-solid" >}} | [`[VulnerabilityOwasp2021Top10!]`](#vulnerabilityowasp2021top10) | **Introduced** in GitLab 18.1. **Status**: Experiment. Filter vulnerabilities by OWASP Top 10 2021 category. Wildcard value `NONE` is also supported but it cannot be combined with other OWASP top 10 2021 values. To use this argument, you must have Elasticsearch configured and the `advanced_vulnerability_management` feature flag enabled. Not supported on Instance Security Dashboard queries. |
|
||||
| <a id="projectvulnerabilitiesprojectid"></a>`projectId` | [`[ID!]`](#id) | Filter vulnerabilities by project. |
|
||||
| <a id="projectvulnerabilitiesreporttype"></a>`reportType` | [`[VulnerabilityReportType!]`](#vulnerabilityreporttype) | Filter vulnerabilities by report type. |
|
||||
|
|
@ -38238,7 +38238,7 @@ Returns [`VulnerabilitySeveritiesCount`](#vulnerabilityseveritiescount).
|
|||
| <a id="projectvulnerabilityseveritiescounthasresolution"></a>`hasResolution` | [`Boolean`](#boolean) | Filter vulnerabilities that do or do not have a resolution. |
|
||||
| <a id="projectvulnerabilityseveritiescountidentifiername"></a>`identifierName` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Filter vulnerabilities by identifier name. Ignored when applied on instance security dashboard queries. |
|
||||
| <a id="projectvulnerabilityseveritiescountimage"></a>`image` | [`[String!]`](#string) | Filter vulnerabilities by location image. When this filter is present, the response only matches entries for a `reportType` that includes `container_scanning`, `cluster_image_scanning`. |
|
||||
| <a id="projectvulnerabilityseveritiescountowasptopten"></a>`owaspTopTen` | [`[VulnerabilityOwaspTop10!]`](#vulnerabilityowasptop10) | Filter vulnerabilities by OWASP Top 10 category. Wildcard value `NONE` is also supported but it cannot be combined with other OWASP top 10 values. Experimental support for OWASP 2021 values is deprecated and the removal is tracked in <https://gitlab.com/gitlab-org/gitlab/-/issues/539250> Instead, use the `owasp_top_ten_2021` argument to continue filtering by OWASP 2021 values. |
|
||||
| <a id="projectvulnerabilityseveritiescountowasptopten"></a>`owaspTopTen` | [`[VulnerabilityOwaspTop10!]`](#vulnerabilityowasptop10) | Filter vulnerabilities by OWASP Top 10 2017 category. Wildcard value `NONE` is also supported but it cannot be combined with other OWASP top 10 values. |
|
||||
| <a id="projectvulnerabilityseveritiescountowasptopten2021"></a>`owaspTopTen2021` {{< icon name="warning-solid" >}} | [`[VulnerabilityOwasp2021Top10!]`](#vulnerabilityowasp2021top10) | **Introduced** in GitLab 18.1. **Status**: Experiment. Filter vulnerabilities by OWASP Top 10 2021 category. Wildcard value `NONE` is also supported but it cannot be combined with other OWASP top 10 2021 values. To use this argument, you must have Elasticsearch configured and the `advanced_vulnerability_management` feature flag enabled. Not supported on Instance Security Dashboard queries. |
|
||||
| <a id="projectvulnerabilityseveritiescountprojectid"></a>`projectId` | [`[ID!]`](#id) | Filter vulnerabilities by project. |
|
||||
| <a id="projectvulnerabilityseveritiescountreporttype"></a>`reportType` | [`[VulnerabilityReportType!]`](#vulnerabilityreporttype) | Filter vulnerabilities by report type. |
|
||||
|
|
@ -47369,36 +47369,17 @@ OwaspTop10 category of the vulnerability.
|
|||
|
||||
| Value | Description |
|
||||
| ----- | ----------- |
|
||||
| <a id="vulnerabilityowasptop10a01_2021"></a>`A01_2021` {{< icon name="warning-solid" >}} | **Introduced** in GitLab 16.8. **Status**: Experiment. A01:2021-Broken Access Control, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a02_2021"></a>`A02_2021` {{< icon name="warning-solid" >}} | **Introduced** in GitLab 16.8. **Status**: Experiment. A02:2021-Cryptographic Failures, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a03_2021"></a>`A03_2021` {{< icon name="warning-solid" >}} | **Introduced** in GitLab 16.8. **Status**: Experiment. A03:2021-Injection, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a04_2021"></a>`A04_2021` {{< icon name="warning-solid" >}} | **Introduced** in GitLab 16.8. **Status**: Experiment. A04:2021-Insecure Design, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a05_2021"></a>`A05_2021` {{< icon name="warning-solid" >}} | **Introduced** in GitLab 16.8. **Status**: Experiment. A05:2021-Security Misconfiguration, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a06_2021"></a>`A06_2021` {{< icon name="warning-solid" >}} | **Introduced** in GitLab 16.8. **Status**: Experiment. A06:2021-Vulnerable and Outdated Components, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a07_2021"></a>`A07_2021` {{< icon name="warning-solid" >}} | **Introduced** in GitLab 16.8. **Status**: Experiment. A07:2021-Identification and Authentication Failures, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a08_2021"></a>`A08_2021` {{< icon name="warning-solid" >}} | **Introduced** in GitLab 16.8. **Status**: Experiment. A08:2021-Software and Data Integrity Failures, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a09_2021"></a>`A09_2021` {{< icon name="warning-solid" >}} | **Introduced** in GitLab 16.8. **Status**: Experiment. A09:2021-Security Logging and Monitoring Failures, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a10_2017"></a>`A10_2017` | A10:2017-Insufficient Logging & Monitoring, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a10_2021"></a>`A10_2021` {{< icon name="warning-solid" >}} | **Introduced** in GitLab 16.8. **Status**: Experiment. A10:2021-Server-Side Request Forgery, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a1_2017"></a>`A1_2017` | A1:2017-Injection, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a1_2021"></a>`A1_2021` {{< icon name="warning-solid" >}} | **Introduced** in GitLab 16.8. **Status**: Experiment. A1:2021-Broken Access Control, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a2_2017"></a>`A2_2017` | A2:2017-Broken Authentication, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a2_2021"></a>`A2_2021` {{< icon name="warning-solid" >}} | **Introduced** in GitLab 16.8. **Status**: Experiment. A2:2021-Cryptographic Failures, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a3_2017"></a>`A3_2017` | A3:2017-Sensitive Data Exposure, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a3_2021"></a>`A3_2021` {{< icon name="warning-solid" >}} | **Introduced** in GitLab 16.8. **Status**: Experiment. A3:2021-Injection, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a4_2017"></a>`A4_2017` | A4:2017-XML External Entities (XXE), OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a4_2021"></a>`A4_2021` {{< icon name="warning-solid" >}} | **Introduced** in GitLab 16.8. **Status**: Experiment. A4:2021-Insecure Design, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a5_2017"></a>`A5_2017` | A5:2017-Broken Access Control, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a5_2021"></a>`A5_2021` {{< icon name="warning-solid" >}} | **Introduced** in GitLab 16.8. **Status**: Experiment. A5:2021-Security Misconfiguration, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a6_2017"></a>`A6_2017` | A6:2017-Security Misconfiguration, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a6_2021"></a>`A6_2021` {{< icon name="warning-solid" >}} | **Introduced** in GitLab 16.8. **Status**: Experiment. A6:2021-Vulnerable and Outdated Components, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a7_2017"></a>`A7_2017` | A7:2017-Cross-Site Scripting (XSS), OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a7_2021"></a>`A7_2021` {{< icon name="warning-solid" >}} | **Introduced** in GitLab 16.8. **Status**: Experiment. A7:2021-Identification and Authentication Failures, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a8_2017"></a>`A8_2017` | A8:2017-Insecure Deserialization, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a8_2021"></a>`A8_2021` {{< icon name="warning-solid" >}} | **Introduced** in GitLab 16.8. **Status**: Experiment. A8:2021-Software and Data Integrity Failures, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a9_2017"></a>`A9_2017` | A9:2017-Using Components with Known Vulnerabilities, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a9_2021"></a>`A9_2021` {{< icon name="warning-solid" >}} | **Introduced** in GitLab 16.8. **Status**: Experiment. A9:2021-Security Logging and Monitoring Failures, OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10none"></a>`NONE` | No OWASP top 10 category. |
|
||||
| <a id="vulnerabilityowasptop10a10_2017"></a>`A10_2017` | A10:2017-Insufficient Logging & Monitoring, OWASP top 10 2017 category. |
|
||||
| <a id="vulnerabilityowasptop10a1_2017"></a>`A1_2017` | A1:2017-Injection, OWASP top 10 2017 category. |
|
||||
| <a id="vulnerabilityowasptop10a2_2017"></a>`A2_2017` | A2:2017-Broken Authentication, OWASP top 10 2017 category. |
|
||||
| <a id="vulnerabilityowasptop10a3_2017"></a>`A3_2017` | A3:2017-Sensitive Data Exposure, OWASP top 10 2017 category. |
|
||||
| <a id="vulnerabilityowasptop10a4_2017"></a>`A4_2017` | A4:2017-XML External Entities (XXE), OWASP top 10 2017 category. |
|
||||
| <a id="vulnerabilityowasptop10a5_2017"></a>`A5_2017` | A5:2017-Broken Access Control, OWASP top 10 2017 category. |
|
||||
| <a id="vulnerabilityowasptop10a6_2017"></a>`A6_2017` | A6:2017-Security Misconfiguration, OWASP top 10 2017 category. |
|
||||
| <a id="vulnerabilityowasptop10a7_2017"></a>`A7_2017` | A7:2017-Cross-Site Scripting (XSS), OWASP top 10 2017 category. |
|
||||
| <a id="vulnerabilityowasptop10a8_2017"></a>`A8_2017` | A8:2017-Insecure Deserialization, OWASP top 10 2017 category. |
|
||||
| <a id="vulnerabilityowasptop10a9_2017"></a>`A9_2017` | A9:2017-Using Components with Known Vulnerabilities, OWASP top 10 2017 category. |
|
||||
| <a id="vulnerabilityowasptop10none"></a>`NONE` | No OWASP top 10 2017 category. |
|
||||
|
||||
### `VulnerabilityReportType`
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
stage: Verify
|
||||
group: Runner
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
description: Set timeouts, protect sensitive information, control behavior with tags and variables, and configure artifact and cache settings of your GitLab Runner.
|
||||
title: Configuring runners
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ features. Premium gets access to only a subset of GitLab Duo features.
|
|||
1. Follow [the process to obtain an Ultimate license](https://handbook.gitlab.com/handbook/engineering/developer-onboarding/#working-on-gitlab-ee-developer-licenses)
|
||||
for your local instance. Start with a GitLab Self-Managed Ultimate license. After you have a GitLab Self-Managed license configured, you can always [simulate a SaaS instance](../ee_features.md#simulate-a-saas-instance) and assign individual groups Premium and Ultimate licenses in the admin panel.
|
||||
1. [Upload your license activation code](../../administration/license.md#activate-gitlab-ee)
|
||||
1. [Set environment variables](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/runit.md#using-environment-variables) in GDK:
|
||||
1. [Set environment variables](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/contributing/runit.md#using-environment-variables) in GDK:
|
||||
|
||||
```shell
|
||||
export GITLAB_LICENSE_MODE=test
|
||||
|
|
|
|||
|
|
@ -30,9 +30,10 @@ You can connect ClickHouse to GitLab either:
|
|||
|
||||
## Supported ClickHouse versions
|
||||
|
||||
| First GitLab version | ClickHouse versions |
|
||||
|-|-|
|
||||
|18.1.0 | 23.x, 24.x, 25.x |
|
||||
| First GitLab version | ClickHouse versions | Comment |
|
||||
|-|-|-|
|
||||
|17.7.0 | 23.x (24.x, 25.x) | For using ClickHouse 24.x and 25.x see the [workaround section](#database-schema-migrations-on-gitlab-1800-and-earlier). |
|
||||
|18.1.0 | 23.x, 24.x, 25.x | |
|
||||
|
||||
{{< alert type="note" >}}
|
||||
|
||||
|
|
@ -136,7 +137,7 @@ To provide GitLab with ClickHouse credentials:
|
|||
To verify that your connection is set up successfully:
|
||||
|
||||
1. Sign in to [Rails console](../administration/operations/rails_console.md#starting-a-rails-console-session)
|
||||
1. Execute the following:
|
||||
1. Execute the following command:
|
||||
|
||||
```ruby
|
||||
ClickHouse::Client.select('SELECT 1', :main)
|
||||
|
|
@ -155,3 +156,32 @@ sudo gitlab-rake gitlab:clickhouse:migrate
|
|||
### Enable ClickHouse for Analytics
|
||||
|
||||
Now that your GitLab instance is connected to ClickHouse, you can enable features to use ClickHouse by [enabling ClickHouse for Analytics](../administration/analytics.md).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Database schema migrations on GitLab 18.0.0 and earlier
|
||||
|
||||
On GitLab 18.0.0 and earlier, running database schema migrations for ClickHouse may fail for ClickHouse 24.x and 25.x with the following error message:
|
||||
|
||||
```plaintext
|
||||
Code: 344. DB::Exception: Projection is fully supported in ReplacingMergeTree with deduplicate_merge_projection_mode = throw. Use 'drop' or 'rebuild' option of deduplicate_merge_projection_mode
|
||||
```
|
||||
|
||||
Without running all migrations, the ClickHouse integration will not work.
|
||||
|
||||
To work around this issue and run the migrations:
|
||||
|
||||
1. Sign in to [Rails console](../administration/operations/rails_console.md#starting-a-rails-console-session)
|
||||
1. Execute the following command:
|
||||
|
||||
```ruby
|
||||
ClickHouse::Client.execute("INSERT INTO schema_migrations (version) VALUES ('20231114142100'), ('20240115162101')", :main)
|
||||
```
|
||||
|
||||
1. Migrate the database again:
|
||||
|
||||
```shell
|
||||
sudo gitlab-rake gitlab:clickhouse:migrate
|
||||
```
|
||||
|
||||
This time the database migration should successfully finish.
|
||||
|
|
|
|||
|
|
@ -302,6 +302,30 @@ To define when offline nodes are automatically deleted:
|
|||
To disable automatic deletion, set to `0`.
|
||||
1. Select **Save changes**.
|
||||
|
||||
## Define the indexing timeout for a project
|
||||
|
||||
{{< history >}}
|
||||
|
||||
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/182581) in GitLab 18.2.
|
||||
|
||||
{{< /history >}}
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- You must have administrator access to the instance.
|
||||
|
||||
You can define the indexing timeout for a project.
|
||||
The default value is `30m` (30 minutes).
|
||||
|
||||
To define the indexing timeout for a project:
|
||||
|
||||
1. On the left sidebar, at the bottom, select **Admin**.
|
||||
1. Select **Settings > Search**.
|
||||
1. Expand **Exact code search configuration**.
|
||||
1. In the **Indexing timeout per project** text box, enter a value
|
||||
(for example, `30m` (30 minutes), `2h` (two hours), or `1d` (one day)).
|
||||
1. Select **Save changes**.
|
||||
|
||||
## Define the retry interval for failed namespaces
|
||||
|
||||
{{< history >}}
|
||||
|
|
|
|||
|
|
@ -12,9 +12,7 @@ and running quickly.
|
|||
| Topic | Description | Good for beginners |
|
||||
|-------|-------------|--------------------|
|
||||
| [GitLab with Git Essentials](https://university.gitlab.com/courses/gitlab-with-git-essentials-s2) | Learn the basics of Git and GitLab in this self-paced course. | {{< icon name="star" >}} |
|
||||
| <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Use GitLab for DevOps](https://www.youtube.com/watch?v=7q9Y1Cv-ib0) (12m 34s) | Use GitLab through the entire DevOps lifecycle, from planning to monitoring. | {{< icon name="star" >}} |
|
||||
| <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [How to start a free trial](https://www.youtube.com/watch?v=dIlBLrXbfrM&list=PLFGfElNsQthYDx0A_FaNNfUm9NHsK6zED&index=63) (3m 01s) | Learn how to start a free 30-day Ultimate trial, and create your first project. | {{< icon name="star" >}} |
|
||||
| [Use the left sidebar to navigate GitLab](left_sidebar/_index.md) | Start navigating the GitLab UI. | {{< icon name="star" >}} |
|
||||
| [Use Markdown at GitLab](../user/markdown.md) | GitLab Flavored Markdown (GLFM) is used in many areas of GitLab, for example, in merge requests. | {{< icon name="star" >}} |
|
||||
| <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [GitLab Continuous Delivery overview](https://www.youtube.com/watch?v=M7rBDZYsx8U&list=PLFGfElNsQthYDx0A_FaNNfUm9NHsK6zED&index=193) (17m 2s) | Learn how to use GitLab features to continuously build, test, and deploy iterative code changes. | |
|
||||
| [Productivity tips](https://about.gitlab.com/blog/2021/02/18/improve-your-gitlab-productivity-with-these-10-tips/) | Get tips to help make you a productive GitLab user. | |
|
||||
| <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Introducing GitLab Service Desk](https://www.youtube.com/watch?v=LDVQXv3I5rI) (6m 50s) | Learn how GitLab [Service Desk](../user/project/service_desk/_index.md) provides an integrated help desk solution to enhance customer support workflows. This video covers key features, such as [custom email addresses](../user/project/service_desk/configure.md#custom-email-address) and [email templates](../user/project/service_desk/configure.md#customize-emails-sent-to-external-participants), ticket management, [comment templates](../user/profile/comment_templates.md), [CRM integration](../user/crm/_index.md), automation using `gitlab-triage` in scheduled CI/CD pipelines, and analytics and [insights](../user/project/insights/_index.md). | |
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ title: GitLab Duo Model Selection
|
|||
|
||||
{{< history >}}
|
||||
|
||||
- [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/17570) for top-level groups in GitLab 18.1 with a [flag](../../administration/feature_flags.md) named `ai_model_switching`. Enabled by default.
|
||||
- [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/17570) for top-level groups in GitLab 18.1 with a [flag](../../administration/feature_flags.md) named `ai_model_switching`. Disabled by default.
|
||||
|
||||
{{< /history >}}
|
||||
|
||||
|
|
|
|||
|
|
@ -96,20 +96,24 @@ To do it, paste the issue URL when
|
|||
|
||||
{{< /details >}}
|
||||
|
||||
If your epic contains one or more [child epics](manage_epics.md#multi-level-child-epics) that
|
||||
have a start or due date, you can go to a [roadmap](../roadmap/_index.md)
|
||||
of the child epics from the epic.
|
||||
|
||||

|
||||
|
||||
<!-- When epics as work items are generally available, the steps below should be the only ones here. -->
|
||||
|
||||
If [the new look for epics](epic_work_items.md) is enabled:
|
||||
|
||||
- On the **Child items** section header, select **More actions** ({{< icon name="ellipsis_v" >}}) **> View on a roadmap**.
|
||||
On the **Child items** section header, select **More actions** ({{< icon name="ellipsis_v" >}}) **> View on a roadmap**.
|
||||
|
||||
A roadmap filtered for the parent epic opens.
|
||||
|
||||
## Epics as work items
|
||||
|
||||
We have changed how epics look by migrating them to a unified framework for work items to better
|
||||
meet the product needs of our Agile Planning offering.
|
||||
|
||||
For more information, see [epic 9290](https://gitlab.com/groups/gitlab-org/-/epics/9290) and the
|
||||
following blog posts:
|
||||
|
||||
- [First look: The new Agile planning experience in GitLab](https://about.gitlab.com/blog/2024/06/18/first-look-the-new-agile-planning-experience-in-gitlab/) (June 2024)
|
||||
- [Unveiling a new epic experience for improved Agile planning](https://about.gitlab.com/blog/2024/07/03/unveiling-a-new-epic-experience-for-improved-agile-planning/) (July 2024)
|
||||
|
||||
If you run into any issues while trying out this change, you can use the
|
||||
[feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/494462) to provide more details.
|
||||
|
||||
## Related topics
|
||||
|
||||
- [Manage epics](manage_epics.md) and multi-level child epics.
|
||||
|
|
|
|||
|
|
@ -1,64 +1,14 @@
|
|||
---
|
||||
stage: Plan
|
||||
group: Product Planning
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
title: Test a new look for epics
|
||||
redirect_to: '../_index.md'
|
||||
remove_date: '2025-09-13'
|
||||
---
|
||||
|
||||
{{< details >}}
|
||||
<!-- markdownlint-disable -->
|
||||
|
||||
- Tier: Premium, Ultimate
|
||||
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
|
||||
- Status: Beta
|
||||
This document was moved to [another location](../_index.md).
|
||||
|
||||
{{< /details >}}
|
||||
|
||||
{{< history >}}
|
||||
|
||||
- [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/9290) in GitLab 17.2 [with a flag](../../../administration/feature_flags.md) named `work_item_epics`. Disabled by default. This feature is in [beta](../../../policy/development_stages_support.md#beta).
|
||||
- Listing epics using the [GraphQL API](../../../api/graphql/reference/_index.md) [introduced](https://gitlab.com/groups/gitlab-org/-/epics/12852) in GitLab 17.4.
|
||||
- [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/470685) in GitLab 17.6.
|
||||
- [Enabled by default on GitLab Self-Managed and GitLab Dedicated](https://gitlab.com/gitlab-org/gitlab/-/issues/468310) in GitLab 17.7.
|
||||
|
||||
{{< /history >}}
|
||||
|
||||
{{< alert type="flag" >}}
|
||||
|
||||
The availability of this feature is controlled by a feature flag.
|
||||
For more information, see the history.
|
||||
|
||||
{{< /alert >}}
|
||||
|
||||
<!-- When epics as work items are generally available and `work_item_epics` flag is removed,
|
||||
incorporate this content into epics/index.md and redirect this page there -->
|
||||
|
||||
We have changed how epics look by migrating them to a unified framework for work items to better
|
||||
meet the product needs of our Agile Planning offering.
|
||||
|
||||
For more information, see [epic 9290](https://gitlab.com/groups/gitlab-org/-/epics/9290) and the
|
||||
following blog posts:
|
||||
|
||||
- [First look: The new Agile planning experience in GitLab](https://about.gitlab.com/blog/2024/06/18/first-look-the-new-agile-planning-experience-in-gitlab/) (June 2024)
|
||||
- [Unveiling a new epic experience for improved Agile planning](https://about.gitlab.com/blog/2024/07/03/unveiling-a-new-epic-experience-for-improved-agile-planning/) (July 2024)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If you run into any issues while navigating your data in the new experience, there are a couple
|
||||
of ways you can try to resolve it.
|
||||
|
||||
### Disable the new experience
|
||||
|
||||
{{< details >}}
|
||||
|
||||
- Offering: GitLab Self-Managed
|
||||
|
||||
{{< /details >}}
|
||||
|
||||
We don't recommend disabling this change, because we'd like your feedback on what you don't like about it.
|
||||
If you have to disable the new experience to unblock your workflow, disable the `work_item_epics`
|
||||
[feature flag](../../../administration/feature_flags.md#how-to-enable-and-disable-features-behind-flags).
|
||||
|
||||
## Feedback
|
||||
|
||||
If you run into any issues while trying out this change, you can use
|
||||
[feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/494462) to provide more details.
|
||||
<!-- This redirect file can be deleted after <2025-09-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/development/documentation/redirects -->
|
||||
---
|
||||
|
|
|
|||
|
|
@ -192,16 +192,10 @@ To open the epic in full view, either:
|
|||
|
||||
{{< /history >}}
|
||||
|
||||
<!-- When epics as work items are GA and feature flag `work_item_epics` is removed, remove the prerequisite below. -->
|
||||
|
||||
If an epic description is long, GitLab displays only part of it.
|
||||
To see the whole description, you must select **Read more**.
|
||||
This truncation makes it easier to find other elements on the page without scrolling through lengthy text.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- [The new look for epics](epic_work_items.md) must be enabled.
|
||||
|
||||
To change whether descriptions are truncated:
|
||||
|
||||
1. On an epic, in the upper-right corner, select **More actions** ({{< icon name="ellipsis_v" >}}).
|
||||
|
|
@ -217,14 +211,8 @@ This setting is remembered and affects all issues, tasks, epics, objectives, and
|
|||
|
||||
{{< /history >}}
|
||||
|
||||
<!-- When epics as work items are GA and feature flag `work_item_epics` is removed, remove the prerequisite below. -->
|
||||
|
||||
Epic attributes are shown in a sidebar to the right of the description when space allows.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- [The new look for epics](epic_work_items.md) must be enabled.
|
||||
|
||||
To hide the sidebar and increase space for the description:
|
||||
|
||||
1. On an epic, in the upper-right corner, select **More actions** ({{< icon name="ellipsis_v" >}}).
|
||||
|
|
@ -259,8 +247,7 @@ This feature is available for testing, but not ready for production use.
|
|||
|
||||
{{< /alert >}}
|
||||
|
||||
If [the new look for epics](epic_work_items.md) is enabled,
|
||||
an epic can be assigned to one or more users.
|
||||
An epic can be assigned to one or more users.
|
||||
|
||||
The assignees can be changed as often as needed.
|
||||
The idea is that the assignees are people responsible for the epic.
|
||||
|
|
@ -282,7 +269,6 @@ If you find a bug, use the
|
|||
|
||||
Prerequisites:
|
||||
|
||||
- [The new look for epics](epic_work_items.md) must be enabled.
|
||||
- You must have at least the Planner role for the group.
|
||||
|
||||
To change the assignee on an epic:
|
||||
|
|
@ -568,25 +554,18 @@ in relation to epics.
|
|||
|
||||
### View issues assigned to an epic
|
||||
|
||||
On the **Child issues and epics** section, you can see epics and issues assigned to this epic.
|
||||
Only epics and issues that you can access show on the list.
|
||||
In the **Child items** section, you can see epics, issues, and tasks assigned to this epic.
|
||||
You can also see any epics, issues, and tasks inherited by descendant items.
|
||||
Only epics, issues, and tasks that you can access show on the list.
|
||||
|
||||
You can always view the issues assigned to the epic if they are in the group's child project.
|
||||
It's possible because the visibility setting of a project must be the same as or less restrictive than
|
||||
of its parent group.
|
||||
|
||||
<!-- When epics as work items are generally available and feature flag `work_item_epics` is removed,
|
||||
use the info below in the main body. -->
|
||||
|
||||
If [the new look for epics](epic_work_items.md) is enabled, this section is named
|
||||
**Child items**.
|
||||
You can also see any epics, issues, and tasks inherited by descendant items.
|
||||
Only epics, issues, and tasks that you can access show on the list.
|
||||
|
||||
### View count and weight of issues in an epic
|
||||
|
||||
On the **Child issues and epics** section header, the number of descendant epics and issues and their total
|
||||
weight is displayed.
|
||||
In the **Child items** section header, the number of descendant epics and issues and their total
|
||||
weight is displayed. Tasks are not included in these counts.
|
||||
|
||||
To see the number of open and closed epics and issues:
|
||||
|
||||
|
|
@ -595,13 +574,6 @@ To see the number of open and closed epics and issues:
|
|||
The numbers reflect all child issues and epics associated with the epic, including those you might
|
||||
not have permission to view.
|
||||
|
||||
<!-- When epics as work items are generally available and feature flag `work_item_epics` is removed,
|
||||
use the info below in the main body. -->
|
||||
|
||||
If [the new look for epics](epic_work_items.md) is enabled, this section is named
|
||||
**Child items**.
|
||||
Tasks are not included in these counts.
|
||||
|
||||
### View epic progress
|
||||
|
||||
{{< history >}}
|
||||
|
|
@ -610,7 +582,8 @@ Tasks are not included in these counts.
|
|||
|
||||
{{< /history >}}
|
||||
|
||||
On the **Child issues and epics** section header, the epic progress percentage is displayed.
|
||||
In the **Child items** section header, the epic progress percentage is displayed.
|
||||
Tasks are not included in this calculation.
|
||||
|
||||
To see the completed and total weight of child issues:
|
||||
|
||||
|
|
@ -619,13 +592,6 @@ To see the completed and total weight of child issues:
|
|||
The weights and progress reflect all issues associated with the epic, including issues you might
|
||||
not have permission to view.
|
||||
|
||||
<!-- When epics as work items are generally available and feature flag `work_item_epics` is removed,
|
||||
use the info below in the main body. -->
|
||||
|
||||
If [the new look for epics](epic_work_items.md) is enabled, this section is named
|
||||
**Child items**.
|
||||
Tasks are not included in this calculation.
|
||||
|
||||
### Health status
|
||||
|
||||
{{< details >}}
|
||||
|
|
@ -667,7 +633,6 @@ To address risks to timely delivery of your planned work, incorporate a review o
|
|||
|
||||
Prerequisites:
|
||||
|
||||
- [The new look for epics](epic_work_items.md) must be enabled.
|
||||
- You must have at least the Planner role for the group.
|
||||
|
||||
To change the health status of an epic:
|
||||
|
|
@ -704,7 +669,7 @@ The maximum number of direct child issues and epics is 5000.
|
|||
{{< /history >}}
|
||||
|
||||
You can add existing issues to an epic, including issues in a project from a [different group hierarchy](_index.md#child-issues-from-different-group-hierarchies).
|
||||
Newly added issues appear at the top of the list of issues in the **Child issues and epics** section.
|
||||
Newly added issues appear at the top of the list of issues in the **Child items** section.
|
||||
|
||||
An epic contains a list of issues and an issue can be set as a child item of at most one epic.
|
||||
When you add a new issue that's already linked to an epic, the issue is automatically unlinked from its
|
||||
|
|
@ -716,7 +681,7 @@ Prerequisites:
|
|||
|
||||
To add an existing issue to an epic:
|
||||
|
||||
1. On the epic's page, under **Child issues and epics**, select **Add**.
|
||||
1. On the epic's page, under **Child items**, select **Add**.
|
||||
1. Select **Add an existing issue**.
|
||||
1. Identify the issue to be added, using either of the following methods:
|
||||
- Paste the link of the issue.
|
||||
|
|
@ -727,12 +692,6 @@ To add an existing issue to an epic:
|
|||
If there are multiple issues to be added, press <kbd>Space</kbd> and repeat this step.
|
||||
1. Select **Add**.
|
||||
|
||||
<!-- When epics as work items are generally available and feature flag `work_item_epics` is removed,
|
||||
use the info below in the main body. -->
|
||||
|
||||
If [the new look for epics](epic_work_items.md) is enabled, this section is named
|
||||
**Child items**.
|
||||
|
||||
#### Create an issue from an epic
|
||||
|
||||
{{< history >}}
|
||||
|
|
@ -756,7 +715,7 @@ Prerequisites:
|
|||
|
||||
To create an issue from an epic:
|
||||
|
||||
1. On the epic's page, under **Child issues and epics**, select **Add**.
|
||||
1. On the epic's page, under **Child items**, select **Add**.
|
||||
1. Select **Add a new issue**.
|
||||
1. Under **Title**, enter the title for the new issue.
|
||||
1. From the **Project** dropdown list, select the project in which the issue should be created.
|
||||
|
|
@ -764,12 +723,6 @@ To create an issue from an epic:
|
|||
|
||||
The new issue is assigned to the epic.
|
||||
|
||||
<!-- When epics as work items are generally available and feature flag `work_item_epics` is removed,
|
||||
use the info below in the main body. -->
|
||||
|
||||
If [the new look for epics](epic_work_items.md) is enabled, this section is named
|
||||
**Child items**.
|
||||
|
||||
### Remove an issue from an epic
|
||||
|
||||
{{< history >}}
|
||||
|
|
@ -801,7 +754,7 @@ To remove an issue from an epic:
|
|||
|
||||
{{< /history >}}
|
||||
|
||||
New issues show at the top of the list in the **Child issues and epics** section.
|
||||
New issues show at the top of the list in the **Child items** section.
|
||||
You can reorder the list of issues by dragging them.
|
||||
|
||||
Prerequisites:
|
||||
|
|
@ -810,15 +763,9 @@ Prerequisites:
|
|||
|
||||
To reorder issues assigned to an epic:
|
||||
|
||||
1. Go to the **Child issues and epics** section.
|
||||
1. Go to the **Child items** section.
|
||||
1. Drag issues into the desired order.
|
||||
|
||||
<!-- When epics as work items are generally available and feature flag `work_item_epics` is removed,
|
||||
use the info below in the main body. -->
|
||||
|
||||
If [the new look for epics](epic_work_items.md) is enabled, this section is named
|
||||
**Child items**.
|
||||
|
||||
### Move issues between epics
|
||||
|
||||
{{< details >}}
|
||||
|
|
@ -834,7 +781,7 @@ If [the new look for epics](epic_work_items.md) is enabled, this section is name
|
|||
|
||||
{{< /history >}}
|
||||
|
||||
New issues appear at the top of the list in the **Child issues and epics**
|
||||
New issues appear at the top of the list in the **Child items**
|
||||
tab. You can move issues from one epic to another.
|
||||
|
||||
Prerequisites:
|
||||
|
|
@ -843,15 +790,9 @@ Prerequisites:
|
|||
|
||||
To move an issue to another epic:
|
||||
|
||||
1. Go to the **Child issues and epics** section.
|
||||
1. Go to the **Child items** section.
|
||||
1. Drag issues into the desired parent epic in the visible hierarchy.
|
||||
|
||||
<!-- When epics as work items are generally available and feature flag `work_item_epics` is removed,
|
||||
use the info below in the main body. -->
|
||||
|
||||
If [the new look for epics](epic_work_items.md) is enabled, this section is named
|
||||
**Child items**.
|
||||
|
||||
### Use an epic template for repeating issues
|
||||
|
||||
You can create a spreadsheet template to manage a pattern of consistently repeating issues.
|
||||
|
|
@ -869,11 +810,7 @@ For an introduction to epic templates, see [GitLab Epics and Epic Template Tip](
|
|||
{{< /details >}}
|
||||
|
||||
You can add any epic that belongs to a group or subgroup of the parent epic's group.
|
||||
New child epics appear at the top of the list of epics in the **Child issues and epics** section.
|
||||
<!-- When epics as work items are generally available and feature flag `work_item_epics` is removed,
|
||||
use the info below in the main body. -->
|
||||
If [the new look for epics](epic_work_items.md) is enabled, this section is named
|
||||
**Child items**.
|
||||
New child epics appear at the top of the list of epics in the **Child items** section.
|
||||
|
||||
When you add an epic that's already linked to a parent epic, the link to its current parent is removed.
|
||||
|
||||
|
|
@ -892,7 +829,6 @@ This helps organize and track related work across multiple epics.
|
|||
|
||||
Prerequisites:
|
||||
|
||||
- [The new look for epics](epic_work_items.md) must be enabled.
|
||||
- You must have at least the Guest role for either the parent epic's group or the child epic's group.
|
||||
|
||||
To add a parent epic:
|
||||
|
|
@ -937,13 +873,7 @@ Prerequisites:
|
|||
|
||||
To view child epics from the parent:
|
||||
|
||||
- In an epic, in the **Child issues and epics** section, select **Roadmap view**.
|
||||
|
||||
<!-- When epics as work items are generally available and feature flag `work_item_epics` is removed,
|
||||
use the info below in the main body. -->
|
||||
|
||||
If [the new look for epics](epic_work_items.md) is enabled, this section is named
|
||||
**Child items**.
|
||||
- In an epic, in the **Child items** section, select **Roadmap view**.
|
||||
|
||||
### Add a child epic to an epic
|
||||
|
||||
|
|
@ -961,22 +891,16 @@ Prerequisites:
|
|||
|
||||
To add a new epic as child epic:
|
||||
|
||||
1. In an epic, in the **Child issues and epics** section, select **Add > Add a new epic**.
|
||||
1. In an epic, in the **Child items** section, select **Add > Add a new epic**.
|
||||
1. Select a group from the dropdown list. The epic's group is selected by default.
|
||||
1. Enter a title for the new epic.
|
||||
1. Select **Create epic**.
|
||||
|
||||
<!-- When epics as work items are generally available and feature flag `work_item_epics` is removed,
|
||||
use the info below in the main body. -->
|
||||
|
||||
If [the new look for epics](epic_work_items.md) is enabled, this section is named
|
||||
**Child items**.
|
||||
|
||||
#### Existing epic
|
||||
|
||||
To add an existing epic as child epic:
|
||||
|
||||
1. In an epic, in the **Child issues and epics** section, select **Add > Add an existing epic**.
|
||||
1. In an epic, in the **Child items** section, select **Add > Add an existing epic**.
|
||||
1. Identify the epic to be added, using either of the following methods:
|
||||
- Paste the link of the epic.
|
||||
- Search for the desired issue by entering part of the epic's title, then selecting the desired match. This search is only available for epics in the same group hierarchy.
|
||||
|
|
@ -984,12 +908,6 @@ To add an existing epic as child epic:
|
|||
If there are multiple epics to be added, press <kbd>Space</kbd> and repeat this step.
|
||||
1. Select **Add**.
|
||||
|
||||
<!-- When epics as work items are generally available and feature flag `work_item_epics` is removed,
|
||||
use the info below in the main body. -->
|
||||
|
||||
If [the new look for epics](epic_work_items.md) is enabled, this section is named
|
||||
**Child items**.
|
||||
|
||||
### Move child epics between epics
|
||||
|
||||
{{< history >}}
|
||||
|
|
@ -998,7 +916,7 @@ If [the new look for epics](epic_work_items.md) is enabled, this section is name
|
|||
|
||||
{{< /history >}}
|
||||
|
||||
New child epics appear at the top of the list in the **Child issues and epics** section.
|
||||
New child epics appear at the top of the list in the **Child items** section.
|
||||
You can move child epics from one epic to another.
|
||||
When you add a new epic that's already linked to a parent epic, the link to its current parent is removed.
|
||||
Issues and child epics cannot be intermingled.
|
||||
|
|
@ -1009,15 +927,9 @@ Prerequisites:
|
|||
|
||||
To move child epics to another epic:
|
||||
|
||||
1. Go to the **Child issues and epics** section.
|
||||
1. Go to the **Child items** section.
|
||||
1. Drag epics into the desired parent epic.
|
||||
|
||||
<!-- When epics as work items are generally available and feature flag `work_item_epics` is removed,
|
||||
use the info below in the main body. -->
|
||||
|
||||
If [the new look for epics](epic_work_items.md) is enabled, this section is named
|
||||
**Child items**.
|
||||
|
||||
### Reorder child epics assigned to an epic
|
||||
|
||||
{{< history >}}
|
||||
|
|
@ -1026,7 +938,7 @@ If [the new look for epics](epic_work_items.md) is enabled, this section is name
|
|||
|
||||
{{< /history >}}
|
||||
|
||||
New child epics appear at the top of the list in the **Child issues and epics** section.
|
||||
New child epics appear at the top of the list in the **Child items** section.
|
||||
You can reorder the list of child epics.
|
||||
|
||||
Prerequisites:
|
||||
|
|
@ -1035,15 +947,9 @@ Prerequisites:
|
|||
|
||||
To reorder child epics assigned to an epic:
|
||||
|
||||
1. Go to the **Child issues and epics** section.
|
||||
1. Go to the **Child items** section.
|
||||
1. Drag epics into the desired order.
|
||||
|
||||
<!-- When epics as work items are generally available and feature flag `work_item_epics` is removed,
|
||||
use the info below in the main body. -->
|
||||
|
||||
If [the new look for epics](epic_work_items.md) is enabled, this section is named
|
||||
**Child items**.
|
||||
|
||||
### Remove a child epic from a parent epic
|
||||
|
||||
{{< history >}}
|
||||
|
|
|
|||
|
|
@ -285,7 +285,7 @@ To link the SAML groups:
|
|||
|
||||
{{< details >}}
|
||||
|
||||
- Offering: GitLab.com
|
||||
- Offering: GitLab.com, GitLab Self-Managed
|
||||
|
||||
{{< /details >}}
|
||||
|
||||
|
|
|
|||
|
|
@ -758,9 +758,6 @@ version to reference other projects from the same namespace.
|
|||
|
||||
GitLab Flavored Markdown recognizes the following:
|
||||
|
||||
<!-- When epics as work items are generally available and feature flag `work_item_epics` is removed,
|
||||
update the Epic entry to use only the `#` symbol. -->
|
||||
|
||||
| References | Input | Cross-project reference | Shortcut inside the same namespace |
|
||||
|--------------------------------------------------------------------------------------|-------------------------------------------------------|------------------------------------------------|------------------------------------|
|
||||
| Specific user | `@user_name` | | |
|
||||
|
|
@ -770,7 +767,7 @@ update the Epic entry to use only the `#` symbol. -->
|
|||
| Issue | ``#123`` | `namespace/project#123` | `project#123` |
|
||||
| Merge request | `!123` | `namespace/project!123` | `project!123` |
|
||||
| Snippet | `$123` | `namespace/project$123` | `project$123` |
|
||||
| [Epic](group/epics/_index.md) | `&123` or ``#123`` (when [the new look for epics](group/epics/epic_work_items.md) is enabled) | `group1/subgroup&123` or `group1/subgroup#123` | |
|
||||
| [Epic](group/epics/_index.md) | `#123` | `group1/subgroup&123` or `group1/subgroup#123` | |
|
||||
| [Iteration](group/iterations/_index.md) | `*iteration:"iteration title"` | | |
|
||||
| [Iteration cadence](group/iterations/_index.md) by ID<sup>1</sup> | `[cadence:123]` | | |
|
||||
| [Iteration cadence](group/iterations/_index.md) by title (one word)<sup>1</sup> | `[cadence:plan]` | | |
|
||||
|
|
@ -819,14 +816,12 @@ For example:
|
|||
{{< history >}}
|
||||
|
||||
- Support for work items (tasks, objectives, and key results) [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/390854) in GitLab 16.0.
|
||||
- Supported for epics in GitLab 17.7, when `work_item_epics` flag got enabled by default.
|
||||
- Generally available for epics in GitLab 18.1.
|
||||
|
||||
{{< /history >}}
|
||||
|
||||
<!-- When epics as work items are generally available and `work_item_epics` flag is removed,
|
||||
refactor the link below and add a history note -->
|
||||
|
||||
To include the title in the rendered link of an epic ([using the new look](group/epics/epic_work_items.md)),
|
||||
issue, task, objective, key result, merge request, or epic:
|
||||
To include the title in the rendered link of an issue, task, objective, key result, merge request, or epic:
|
||||
|
||||
- Add a plus (`+`) at the end of the reference.
|
||||
|
||||
|
|
@ -840,14 +835,12 @@ URL references like `https://gitlab.com/gitlab-org/gitlab/-/issues/1234+` are al
|
|||
|
||||
- Support for issues and merge requests [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/386937) in GitLab 15.10.
|
||||
- Support for work items (tasks, objectives, and key results) [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/390854) in GitLab 16.0.
|
||||
- Supported for epics in GitLab 17.7, when `work_item_epics` flag got enabled by default.
|
||||
- Generally available for epics in GitLab 18.1.
|
||||
|
||||
{{< /history >}}
|
||||
|
||||
<!-- When epics as work items are generally available and `work_item_epics` flag is removed,
|
||||
refactor the link below and add a history note -->
|
||||
|
||||
To include an extended summary in the rendered link of an epic ([using the new look](group/epics/epic_work_items.md)),
|
||||
issue, task, objective, key result, or merge request:
|
||||
To include an extended summary in the rendered link of an epic, issue, task, objective, key result, or merge request:
|
||||
|
||||
- Add a `+s` at the end of the reference.
|
||||
|
||||
|
|
|
|||
|
|
@ -5,51 +5,102 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
title: GitLab Release CLI tool
|
||||
---
|
||||
|
||||
**The `release-cli` is in maintenance mode**.
|
||||
{{< alert type="warning" >}}
|
||||
|
||||
**The `release-cli` is in maintenance mode**.
|
||||
The `release-cli` does not accept new features.
|
||||
All new feature development happens in the `glab` CLI,
|
||||
so you should use the [`glab` CLI](../../../editor_extensions/gitlab_cli/_index.md) whenever possible.
|
||||
You can use [the feedback issue](https://gitlab.com/gitlab-org/cli/-/issues/7859) to share any comments.
|
||||
|
||||
## Switch from `release-cli` to `glab` CLI
|
||||
|
||||
- For API usage details, see [the `glab` CLI project documentation](https://gitlab.com/gitlab-org/cli).
|
||||
- With a CI/CD job and the [`release`](../../../ci/yaml/_index.md#release) keyword,
|
||||
change the job's `image` to use the `cli:latest` image. For example:
|
||||
|
||||
```yaml
|
||||
release_job:
|
||||
stage: release
|
||||
image: registry.gitlab.com/gitlab-org/cli:latest
|
||||
rules:
|
||||
- if: $CI_COMMIT_TAG
|
||||
script:
|
||||
- echo "Running the release job."
|
||||
release:
|
||||
tag_name: $CI_COMMIT_TAG
|
||||
name: 'Release $CI_COMMIT_TAG'
|
||||
description: 'Release created using the cli.'
|
||||
```
|
||||
|
||||
## Fall back to `release-cli`
|
||||
|
||||
{{< history >}}
|
||||
|
||||
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/524346) in GitLab 18.0, [with a flag](../../../administration/feature_flags.md) named `ci_glab_for_release`. Enabled by default.
|
||||
|
||||
{{< /history >}}
|
||||
|
||||
{{< alert type="flag" >}}
|
||||
|
||||
The availability of this feature is controlled by a feature flag. For more information, see the history.
|
||||
The `release-cli` is in maintenance mode, and [issue cli#7450](https://gitlab.com/gitlab-org/cli/-/issues/7450) proposes to deprecate it as the `glab` CLI matures.
|
||||
|
||||
{{< /alert >}}
|
||||
|
||||
CI/CD jobs that use the `release` keyword use a script that falls back to using `release-cli`
|
||||
if the required `glab` version is not available on the runner. The fallback logic
|
||||
is a safe-guard to ensure that projects that have not yet migrated to use `glab` CLI
|
||||
can continue working.
|
||||
The [GitLab Release CLI (`release-cli`)](https://gitlab.com/gitlab-org/release-cli)
|
||||
is a command-line tool for managing releases from the command line or from a CI/CD pipeline.
|
||||
You can use the release CLI to create, update, modify, and delete releases.
|
||||
|
||||
This fallback is [scheduled to be removed](https://gitlab.com/gitlab-org/gitlab/-/issues/537919)
|
||||
in GitLab 19.0 with the removal of `release-cli`.
|
||||
When you [use a CI/CD job to create a release](_index.md#creating-a-release-by-using-a-cicd-job),
|
||||
the `release` keyword entries are transformed into Bash commands and sent to the Docker
|
||||
container containing the `release-cli` tool. The tool then creates the release.
|
||||
|
||||
You can also call the `release-cli` tool directly from a [`script`](../../../ci/yaml/_index.md#script).
|
||||
For example:
|
||||
|
||||
```shell
|
||||
release-cli create --name "Release $CI_COMMIT_SHA" --description \
|
||||
"Created using the release-cli $EXTRA_DESCRIPTION" \
|
||||
--tag-name "v${MAJOR}.${MINOR}.${REVISION}" --ref "$CI_COMMIT_SHA" \
|
||||
--released-at "2020-07-15T08:00:00Z" --milestone "m1" --milestone "m2" --milestone "m3" \
|
||||
--assets-link "{\"name\":\"asset1\",\"url\":\"https://example.com/assets/1\",\"link_type\":\"other\"}"
|
||||
```
|
||||
|
||||
## Install the `release-cli` for the Shell executor
|
||||
|
||||
{{< details >}}
|
||||
|
||||
- Tier: Free, Premium, Ultimate
|
||||
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
|
||||
|
||||
{{< /details >}}
|
||||
|
||||
The `release-cli` binaries are [available in the package registry](https://gitlab.com/gitlab-org/release-cli/-/packages).
|
||||
|
||||
When you use a runner with the Shell executor, you can download and install
|
||||
the `release-cli` manually for your [supported OS and architecture](https://gitlab.com/gitlab-org/release-cli/-/packages).
|
||||
Once installed, [the `release` keyword](../../../ci/yaml/_index.md#release) is available to use in your CI/CD jobs.
|
||||
|
||||
### Install on Unix/Linux
|
||||
|
||||
1. Download the binary for your system from the GitLab package registry.
|
||||
For example, if you use an amd64 system:
|
||||
|
||||
```shell
|
||||
curl --location --output /usr/local/bin/release-cli "https://gitlab.com/api/v4/projects/gitlab-org%2Frelease-cli/packages/generic/release-cli/latest/release-cli-linux-amd64"
|
||||
```
|
||||
|
||||
1. Give it permissions to execute:
|
||||
|
||||
```shell
|
||||
sudo chmod +x /usr/local/bin/release-cli
|
||||
```
|
||||
|
||||
1. Verify `release-cli` is available:
|
||||
|
||||
```shell
|
||||
$ release-cli -v
|
||||
|
||||
release-cli version 0.15.0
|
||||
```
|
||||
|
||||
### Install on Windows PowerShell
|
||||
|
||||
1. Create a folder somewhere in your system, for example `C:\GitLab\Release-CLI\bin`
|
||||
|
||||
```shell
|
||||
New-Item -Path 'C:\GitLab\Release-CLI\bin' -ItemType Directory
|
||||
```
|
||||
|
||||
1. Download the executable file:
|
||||
|
||||
```shell
|
||||
PS C:\> Invoke-WebRequest -Uri "https://gitlab.com/api/v4/projects/gitlab-org%2Frelease-cli/packages/generic/release-cli/latest/release-cli-windows-amd64.exe" -OutFile "C:\GitLab\Release-CLI\bin\release-cli.exe"
|
||||
|
||||
Directory: C:\GitLab\Release-CLI
|
||||
Mode LastWriteTime Length Name
|
||||
---- ------------- ------ ----
|
||||
d----- 3/16/2021 4:17 AM bin
|
||||
```
|
||||
|
||||
1. Add the directory to your `$env:PATH`:
|
||||
|
||||
```shell
|
||||
$env:PATH += ";C:\GitLab\Release-CLI\bin"
|
||||
```
|
||||
|
||||
1. Verify `release-cli` is available:
|
||||
|
||||
```shell
|
||||
PS C:\> release-cli -v
|
||||
|
||||
release-cli version 0.15.0
|
||||
```
|
||||
|
|
|
|||
|
|
@ -94,14 +94,27 @@ Check if the repository owner is specified in the URL of your mirrored repositor
|
|||
|
||||
When connecting to the Cloud or self-hosted Bitbucket repository for mirroring, the repository owner is required in the string.
|
||||
|
||||
## Push mirror: `LFS objects are missing`
|
||||
|
||||
You might get an error that states:
|
||||
|
||||
```plaintext
|
||||
GitLab: GitLab: LFS objects are missing. Ensure LFS is properly set up or try a manual "git lfs push --all".
|
||||
```
|
||||
|
||||
This issue occurs when you use an SSH repository URL for push mirroring.
|
||||
Push mirroring to transfer LFS files over SSH is not supported.
|
||||
|
||||
The workaround is to use an HTTPS repository URL instead of SSH for your push mirror.
|
||||
|
||||
An [issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/249587) to fix this problem.
|
||||
|
||||
## Pull mirror is missing LFS files
|
||||
|
||||
In some cases, pull mirroring does not transfer LFS files. This issue occurs when:
|
||||
In some cases, pull mirroring does not transfer LFS files.
|
||||
This issue occurs when you use an SSH repository URL.
|
||||
|
||||
- You use an SSH repository URL. The workaround is to use an HTTPS repository URL instead.
|
||||
An issue exists [to fix this problem for SSH URLs](https://gitlab.com/gitlab-org/gitlab/-/issues/11997).
|
||||
- You mirror an external repository using object storage.
|
||||
An issue exists [to fix this problem](https://gitlab.com/gitlab-org/gitlab/-/issues/335495).
|
||||
The workaround is to use an HTTPS repository URL instead.
|
||||
|
||||
## Pull mirroring is not triggering pipelines
|
||||
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ module API
|
|||
project.build_allow_git_fetch ? 'fetch' : 'clone'
|
||||
end
|
||||
expose :keep_latest_artifacts_available?, as: :keep_latest_artifact, documentation: { type: 'boolean' }
|
||||
expose :restrict_user_defined_variables, documentation: { type: 'boolean' }
|
||||
expose(:restrict_user_defined_variables, documentation: { type: 'boolean' }) { |p, _| p.restrict_user_defined_variables? }
|
||||
expose :ci_pipeline_variables_minimum_override_role, documentation: { type: 'string' }
|
||||
expose :runner_token_expiration_interval, documentation: { type: 'integer', example: 3600 }
|
||||
expose :group_runners_enabled, documentation: { type: 'boolean' }
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ module Gitlab
|
|||
|
||||
prefix = side == :old ? "L" : "R"
|
||||
position = side == :old ? old_pos : new_pos
|
||||
"line_#{file_hash}_#{prefix}#{position}"
|
||||
"line_#{file_hash[0..8]}_#{prefix}#{position}"
|
||||
end
|
||||
|
||||
def legacy_id(file_path)
|
||||
|
|
|
|||
|
|
@ -6548,6 +6548,9 @@ msgstr ""
|
|||
msgid "All threads resolved!"
|
||||
msgstr ""
|
||||
|
||||
msgid "All to-do items"
|
||||
msgstr ""
|
||||
|
||||
msgid "All users"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -32795,6 +32798,9 @@ msgstr ""
|
|||
msgid "Indexing status"
|
||||
msgstr ""
|
||||
|
||||
msgid "Indexing timeout per project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -40084,6 +40090,9 @@ msgstr ""
|
|||
msgid "Must be in the following format: `30m`, `2h`, or `1d`"
|
||||
msgstr ""
|
||||
|
||||
msgid "Must be in the following format: `30m`, `2h`, or `1d`."
|
||||
msgstr ""
|
||||
|
||||
msgid "Must be in the following format: `30m`, `2h`, or `1d`. Set to `%{val}` for no retries."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -140,7 +140,6 @@ spec/frontend/ref/init_ambiguous_ref_modal_spec.js
|
|||
spec/frontend/releases/components/asset_links_form_spec.js
|
||||
spec/frontend/repository/components/table/index_spec.js
|
||||
spec/frontend/repository/components/table/row_spec.js
|
||||
spec/frontend/search/sidebar/components/checkbox_filter_spec.js
|
||||
spec/frontend/set_status_modal/user_profile_set_status_wrapper_spec.js
|
||||
spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js
|
||||
spec/frontend/sidebar/components/confidential/confidentiality_dropdown_spec.js
|
||||
|
|
|
|||
|
|
@ -43,12 +43,6 @@ RSpec.describe RapidDiffs::Viewers::Text::InlineHunkComponent, type: :component,
|
|||
expect(page).to have_selector("a[href='##{new_line_id}']")
|
||||
end
|
||||
|
||||
it "renders legacy line id" do
|
||||
line_id = diff_file.line_code(lines.second)
|
||||
render_component
|
||||
expect(page).to have_selector("[data-legacy-id='#{line_id}']")
|
||||
end
|
||||
|
||||
it "renders expand up" do
|
||||
match_line = Gitlab::Diff::Line.new("", 'match', 100, 0, 0)
|
||||
diff_hunk = Gitlab::Diff::ViewerHunk.new(
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ RSpec.describe RapidDiffs::Viewers::Text::LineNumberComponent, type: :component,
|
|||
expect(link[:'data-line-number']).to eq(old_line.old_pos.to_s)
|
||||
expect(link[:'aria-label']).to eq("Removed line #{old_line.old_pos}")
|
||||
expect(td[:id]).to eq(old_line.id(diff_file.file_hash, :old))
|
||||
expect(td[:'data-legacy-id']).to eq(diff_file.line_code(old_line))
|
||||
expect(page).to have_selector('[data-position="old"]')
|
||||
end
|
||||
|
||||
|
|
@ -56,7 +55,6 @@ RSpec.describe RapidDiffs::Viewers::Text::LineNumberComponent, type: :component,
|
|||
expect(link[:'data-line-number']).to eq(new_line.new_pos.to_s)
|
||||
expect(link[:'aria-label']).to eq("Added line #{old_line.new_pos}")
|
||||
expect(td[:id]).to eq(new_line.id(diff_file.file_hash, :new))
|
||||
expect(td[:'data-legacy-id']).to eq(diff_file.line_code(new_line))
|
||||
expect(page).to have_selector('[data-position="new"]')
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -43,12 +43,6 @@ RSpec.describe RapidDiffs::Viewers::Text::ParallelHunkComponent, type: :componen
|
|||
expect(page).to have_selector("a[href='##{new_line_id}']")
|
||||
end
|
||||
|
||||
it "renders legacy line id" do
|
||||
line_id = diff_file.line_code(old_line)
|
||||
render_component
|
||||
expect(page).to have_selector("[data-legacy-id='#{line_id}']")
|
||||
end
|
||||
|
||||
it "renders expand up" do
|
||||
match_line = Gitlab::Diff::Line.new("", 'match', 1, 0, 0)
|
||||
diff_hunk = Gitlab::Diff::ViewerHunk.new(
|
||||
|
|
|
|||
|
|
@ -182,8 +182,7 @@ RSpec.describe Projects::PipelineSchedulesController, feature_category: :continu
|
|||
|
||||
context 'when the user is not allowed to create a pipeline schedule with variables' do
|
||||
before do
|
||||
project.update!(restrict_user_defined_variables: true,
|
||||
ci_pipeline_variables_minimum_override_role: :maintainer)
|
||||
project.update!(ci_pipeline_variables_minimum_override_role: :maintainer)
|
||||
end
|
||||
|
||||
it 'does not create a new schedule' do
|
||||
|
|
@ -277,8 +276,7 @@ RSpec.describe Projects::PipelineSchedulesController, feature_category: :continu
|
|||
|
||||
context 'when the user is not allowed to update pipeline schedule variables' do
|
||||
before do
|
||||
project.update!(restrict_user_defined_variables: true,
|
||||
ci_pipeline_variables_minimum_override_role: :maintainer)
|
||||
project.update!(ci_pipeline_variables_minimum_override_role: :maintainer)
|
||||
end
|
||||
|
||||
it 'does not update the schedule' do
|
||||
|
|
|
|||
|
|
@ -67,7 +67,6 @@ FactoryBot.define do
|
|||
import_last_error { nil }
|
||||
forward_deployment_enabled { nil }
|
||||
forward_deployment_rollback_allowed { nil }
|
||||
restrict_user_defined_variables { nil }
|
||||
ci_outbound_job_token_scope_enabled { nil }
|
||||
ci_inbound_job_token_scope_enabled { nil }
|
||||
runners_token { nil }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,207 @@
|
|||
import Vue, { nextTick } from 'vue';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import { GlButton } from '@gitlab/ui';
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import TodosWidget from '~/homepage/components/todos_widget.vue';
|
||||
import TodoItem from '~/todos/components/todo_item.vue';
|
||||
import getTodosQuery from '~/todos/components/queries/get_todos.query.graphql';
|
||||
import { TABS_INDICES } from '~/todos/constants';
|
||||
import * as Sentry from '~/sentry/sentry_browser_wrapper';
|
||||
import { todosResponse } from '../todos/mock_data';
|
||||
|
||||
Vue.use(VueApollo);
|
||||
|
||||
jest.mock('~/sentry/sentry_browser_wrapper', () => ({
|
||||
captureException: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('TodosWidget', () => {
|
||||
let wrapper;
|
||||
|
||||
const todosQuerySuccessHandler = jest.fn().mockResolvedValue(todosResponse);
|
||||
const todosQueryErrorHandler = jest.fn().mockRejectedValue(new Error('GraphQL Error'));
|
||||
|
||||
const createComponent = ({ todosQueryHandler = todosQuerySuccessHandler } = {}) => {
|
||||
const mockApollo = createMockApollo([[getTodosQuery, todosQueryHandler]]);
|
||||
|
||||
wrapper = shallowMountExtended(TodosWidget, {
|
||||
apolloProvider: mockApollo,
|
||||
});
|
||||
};
|
||||
|
||||
const findTodoItems = () => wrapper.findAllComponents(TodoItem);
|
||||
const findFirstTodoItem = () => wrapper.findComponent(TodoItem);
|
||||
const findRefreshButton = () => wrapper.findComponent(GlButton);
|
||||
const findAllTodosLink = () => wrapper.find('a[href="/dashboard/todos"]');
|
||||
|
||||
describe('rendering', () => {
|
||||
it('shows a refresh button with correct props', () => {
|
||||
createComponent();
|
||||
|
||||
const refreshButton = findRefreshButton();
|
||||
expect(refreshButton.exists()).toBe(true);
|
||||
expect(refreshButton.props('icon')).toBe('retry');
|
||||
});
|
||||
|
||||
it('shows a link to all todos', () => {
|
||||
createComponent();
|
||||
|
||||
const link = findAllTodosLink();
|
||||
expect(link.exists()).toBe(true);
|
||||
expect(link.text()).toBe('All to-do items');
|
||||
expect(link.attributes('href')).toBe('/dashboard/todos');
|
||||
});
|
||||
});
|
||||
|
||||
describe('loading state', () => {
|
||||
it('shows loading state on refresh button while fetching todos', () => {
|
||||
createComponent();
|
||||
|
||||
expect(findRefreshButton().props('loading')).toBe(true);
|
||||
});
|
||||
|
||||
it('hides loading state after todos are fetched', async () => {
|
||||
createComponent();
|
||||
await waitForPromises();
|
||||
|
||||
expect(findRefreshButton().props('loading')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GraphQL query', () => {
|
||||
it('makes the correct GraphQL query with proper variables', () => {
|
||||
createComponent();
|
||||
|
||||
expect(todosQuerySuccessHandler).toHaveBeenCalledWith({
|
||||
first: 5,
|
||||
state: ['pending'],
|
||||
});
|
||||
});
|
||||
|
||||
it('updates component data when query resolves', async () => {
|
||||
createComponent();
|
||||
await waitForPromises();
|
||||
|
||||
expect(wrapper.vm.currentUserId).toBe(todosResponse.data.currentUser.id);
|
||||
expect(wrapper.vm.todos).toHaveLength(todosResponse.data.currentUser.todos.nodes.length);
|
||||
});
|
||||
|
||||
it('handles empty todos response gracefully', async () => {
|
||||
const emptyResponse = {
|
||||
data: {
|
||||
currentUser: {
|
||||
id: 'user-1',
|
||||
todos: {
|
||||
nodes: [],
|
||||
pageInfo: {
|
||||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
startCursor: null,
|
||||
endCursor: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const emptyQueryHandler = jest.fn().mockResolvedValue(emptyResponse);
|
||||
createComponent({ todosQueryHandler: emptyQueryHandler });
|
||||
await waitForPromises();
|
||||
|
||||
expect(wrapper.vm.todos).toEqual([]);
|
||||
expect(findTodoItems()).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('captures error with Sentry when query fails', async () => {
|
||||
createComponent({ todosQueryHandler: todosQueryErrorHandler });
|
||||
await waitForPromises();
|
||||
|
||||
expect(Sentry.captureException).toHaveBeenCalledWith(expect.any(Error));
|
||||
});
|
||||
});
|
||||
|
||||
describe('todo items', () => {
|
||||
beforeEach(async () => {
|
||||
createComponent();
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('renders the correct number of todo items', () => {
|
||||
expect(findTodoItems()).toHaveLength(todosResponse.data.currentUser.todos.nodes.length);
|
||||
});
|
||||
|
||||
it('passes the correct props to todo items', () => {
|
||||
expect(findFirstTodoItem().props('todo')).toEqual(
|
||||
todosResponse.data.currentUser.todos.nodes[0],
|
||||
);
|
||||
});
|
||||
|
||||
it('refetches todos when a todo item changes', async () => {
|
||||
// Reset call count after initial query
|
||||
todosQuerySuccessHandler.mockClear();
|
||||
|
||||
const firstTodoItem = findFirstTodoItem();
|
||||
expect(firstTodoItem.exists()).toBe(true);
|
||||
|
||||
firstTodoItem.vm.$emit('change');
|
||||
await waitForPromises();
|
||||
|
||||
expect(todosQuerySuccessHandler).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('refresh functionality', () => {
|
||||
beforeEach(async () => {
|
||||
createComponent();
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('refetches todos when refresh button is clicked', async () => {
|
||||
todosQuerySuccessHandler.mockClear();
|
||||
|
||||
await findRefreshButton().vm.$emit('click');
|
||||
await waitForPromises();
|
||||
|
||||
expect(todosQuerySuccessHandler).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('shows loading state during refresh', async () => {
|
||||
const refreshButton = findRefreshButton();
|
||||
|
||||
await waitForPromises();
|
||||
expect(refreshButton.props('loading')).toBe(false);
|
||||
|
||||
refreshButton.vm.$emit('click');
|
||||
await nextTick();
|
||||
expect(refreshButton.props('loading')).toBe(true);
|
||||
|
||||
await waitForPromises();
|
||||
expect(refreshButton.props('loading')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('provide/inject', () => {
|
||||
it('provides the correct values to child components', () => {
|
||||
createComponent();
|
||||
|
||||
const provided = wrapper.vm.$options.provide.call(wrapper.vm);
|
||||
|
||||
expect(provided.currentTab).toBe(TABS_INDICES.pending);
|
||||
expect(provided.currentTime).toBeInstanceOf(Date);
|
||||
expect(provided.currentUserId).toBeDefined();
|
||||
});
|
||||
|
||||
it('provides reactive currentUserId after query resolves', async () => {
|
||||
createComponent();
|
||||
|
||||
const provided = wrapper.vm.$options.provide.call(wrapper.vm);
|
||||
expect(provided.currentUserId.value).toBeNull();
|
||||
|
||||
await waitForPromises();
|
||||
|
||||
expect(provided.currentUserId.value).toBe(todosResponse.data.currentUser.id);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -29,7 +29,6 @@ describe('TodoItemBody', () => {
|
|||
const createComponent = (todoExtras = {}, otherProps = {}) => {
|
||||
wrapper = shallowMount(TodoItemBody, {
|
||||
propsData: {
|
||||
currentUserId: '1',
|
||||
todo: {
|
||||
author: {
|
||||
id: '2',
|
||||
|
|
@ -46,6 +45,9 @@ describe('TodoItemBody', () => {
|
|||
isHiddenBySaml: false,
|
||||
...otherProps,
|
||||
},
|
||||
provide: {
|
||||
currentUserId: '1',
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -136,18 +138,15 @@ describe('TodoItemBody', () => {
|
|||
|
||||
describe('when current user is the author', () => {
|
||||
it('renders "You" instead of author name', () => {
|
||||
createComponent({ author: { id: '2' } }, { currentUserId: '2' });
|
||||
createComponent({ author: { id: '1' } });
|
||||
expect(wrapper.text()).toContain('You');
|
||||
});
|
||||
|
||||
it('renders correct text for self-assigned action', () => {
|
||||
createComponent(
|
||||
{
|
||||
author: { id: '2' },
|
||||
action: TODO_ACTION_TYPE_ASSIGNED,
|
||||
},
|
||||
{ currentUserId: '2' },
|
||||
);
|
||||
createComponent({
|
||||
author: { id: '1' },
|
||||
action: TODO_ACTION_TYPE_ASSIGNED,
|
||||
});
|
||||
expect(wrapper.text()).toContain('assigned to yourself.');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -112,17 +112,26 @@ describe('TodoItem', () => {
|
|||
});
|
||||
|
||||
describe('multi-select checkbox', () => {
|
||||
it('renders a checkbox', () => {
|
||||
createComponent();
|
||||
expect(wrapper.findComponent(GlFormCheckbox).exists()).toBe(true);
|
||||
describe('with `selectable` prop `false` (default)', () => {
|
||||
it('renders a checkbox', () => {
|
||||
createComponent();
|
||||
expect(wrapper.findComponent(GlFormCheckbox).exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('emits select-change event when checkbox changes', async () => {
|
||||
createComponent();
|
||||
const checkbox = wrapper.findComponent(GlFormCheckbox);
|
||||
await checkbox.vm.$emit('change', true);
|
||||
describe('with `selectable` prop `true`', () => {
|
||||
it('renders a checkbox', () => {
|
||||
createComponent({ selectable: true });
|
||||
expect(wrapper.findComponent(GlFormCheckbox).exists()).toBe(true);
|
||||
});
|
||||
|
||||
expect(wrapper.emitted('select-change')[0]).toEqual([MR_REVIEW_REQUEST_TODO.id, true]);
|
||||
it('emits select-change event when checkbox changes', async () => {
|
||||
createComponent({ selectable: true });
|
||||
const checkbox = wrapper.findComponent(GlFormCheckbox);
|
||||
await checkbox.vm.$emit('change', true);
|
||||
|
||||
expect(wrapper.emitted('select-change')[0]).toEqual([MR_REVIEW_REQUEST_TODO.id, true]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,12 @@ import TodosFilterBar from '~/todos/components/todos_filter_bar.vue';
|
|||
import TodosBulkBar from '~/todos/components/todos_bulk_bar.vue';
|
||||
import TodosPagination, { CURSOR_CHANGED_EVENT } from '~/todos/components/todos_pagination.vue';
|
||||
import getTodosQuery from '~/todos/components/queries/get_todos.query.graphql';
|
||||
import { INSTRUMENT_TAB_LABELS, STATUS_BY_TAB, TODO_WAIT_BEFORE_RELOAD } from '~/todos/constants';
|
||||
import {
|
||||
INSTRUMENT_TAB_LABELS,
|
||||
STATUS_BY_TAB,
|
||||
TABS_INDICES,
|
||||
TODO_WAIT_BEFORE_RELOAD,
|
||||
} from '~/todos/constants';
|
||||
import { mockTracking, unmockTracking } from 'jest/__helpers__/tracking_helper';
|
||||
import getPendingTodosCount from '~/todos/components/queries/get_pending_todos_count.query.graphql';
|
||||
import {
|
||||
|
|
@ -461,6 +466,10 @@ describe('TodosApp', () => {
|
|||
});
|
||||
|
||||
describe('bulk actions', () => {
|
||||
it('renders TodoItems with `selectable` prop', () => {
|
||||
expect(findFirstTodoItem().props('selectable')).toBe(true);
|
||||
});
|
||||
|
||||
it('shows bulk bar when items are selected', async () => {
|
||||
expect(findBulkBar().isVisible()).toBe(false);
|
||||
|
||||
|
|
@ -490,4 +499,27 @@ describe('TodosApp', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('provide/inject', () => {
|
||||
it('provides the correct values to child components', () => {
|
||||
createComponent();
|
||||
|
||||
const provided = wrapper.vm.$options.provide.call(wrapper.vm);
|
||||
|
||||
expect(provided.currentTab.value).toBe(TABS_INDICES.pending);
|
||||
expect(provided.currentTime.value).toBeInstanceOf(Date);
|
||||
expect(provided.currentUserId).toBeDefined();
|
||||
});
|
||||
|
||||
it('provides reactive currentUserId after query resolves', async () => {
|
||||
createComponent();
|
||||
|
||||
const provided = wrapper.vm.$options.provide.call(wrapper.vm);
|
||||
expect(provided.currentUserId.value).toBeNull();
|
||||
|
||||
await waitForPromises();
|
||||
|
||||
expect(provided.currentUserId.value).toBe(todosResponse.data.currentUser.id);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -862,6 +862,6 @@ RSpec.describe DiffHelper, feature_category: :code_review_workflow do
|
|||
describe "#file_heading_id" do
|
||||
subject { helper.file_heading_id(diff_file) }
|
||||
|
||||
it { is_expected.to eq("#{diff_file.file_hash}-heading") }
|
||||
it { is_expected.to eq("#{diff_file.file_hash[0..8]}-heading") }
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Build::Associations, feature_categor
|
|||
|
||||
context 'when project setting restrict_user_defined_variables is enabled' do
|
||||
before do
|
||||
project.update!(restrict_user_defined_variables: true, ci_pipeline_variables_minimum_override_role: :maintainer)
|
||||
project.update!(ci_pipeline_variables_minimum_override_role: :maintainer)
|
||||
end
|
||||
|
||||
context 'when user is developer' do
|
||||
|
|
|
|||
|
|
@ -173,14 +173,14 @@ RSpec.describe Gitlab::Diff::Line do
|
|||
)
|
||||
end
|
||||
|
||||
let(:file_hash) { 'foo' }
|
||||
let(:file_hash) { '1234567890' }
|
||||
|
||||
it 'returns the correct old side ID' do
|
||||
expect(line.id(file_hash, :old)).to eq("line_#{file_hash}_L#{line.old_pos}")
|
||||
expect(line.id(file_hash, :old)).to eq("line_#{file_hash[0..8]}_L#{line.old_pos}")
|
||||
end
|
||||
|
||||
it 'returns the correct new side ID' do
|
||||
expect(line.id(file_hash, :new)).to eq("line_#{file_hash}_R#{line.new_pos}")
|
||||
expect(line.id(file_hash, :new)).to eq("line_#{file_hash[0..8]}_R#{line.new_pos}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ RSpec.describe ProjectCiCdSetting, feature_category: :continuous_integration do
|
|||
it 'enables restrict_user_defined_variables' do
|
||||
setting.pipeline_variables_minimum_override_role = role if role
|
||||
|
||||
expect(project.restrict_user_defined_variables).to be_truthy
|
||||
expect(project.restrict_user_defined_variables?).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -80,7 +80,7 @@ RSpec.describe ProjectCiCdSetting, feature_category: :continuous_integration do
|
|||
it 'disables restrict_user_defined_variables' do
|
||||
setting.pipeline_variables_minimum_override_role = role if role
|
||||
|
||||
expect(project.restrict_user_defined_variables).to be_falsey
|
||||
expect(project.restrict_user_defined_variables?).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -108,7 +108,6 @@ RSpec.describe ProjectCiCdSetting, feature_category: :continuous_integration do
|
|||
|
||||
before do
|
||||
setting.pipeline_variables_minimum_override_role = :maintainer
|
||||
setting.restrict_user_defined_variables = true
|
||||
end
|
||||
|
||||
it 'returns the set role' do
|
||||
|
|
@ -173,18 +172,17 @@ RSpec.describe ProjectCiCdSetting, feature_category: :continuous_integration do
|
|||
end
|
||||
|
||||
it 'disables restrict_user_defined_variables' do
|
||||
expect(setting.restrict_user_defined_variables).to be false
|
||||
expect(setting.restrict_user_defined_variables?).to be false
|
||||
end
|
||||
end
|
||||
|
||||
context 'when setting nil value' do
|
||||
before do
|
||||
setting.restrict_user_defined_variables = false
|
||||
setting.pipeline_variables_minimum_override_role = nil
|
||||
end
|
||||
|
||||
it 'does not change the current settings' do
|
||||
expect(setting.restrict_user_defined_variables).to be false
|
||||
expect(setting.restrict_user_defined_variables?).to be true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1540,7 +1540,6 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
|
|||
'forward_deployment_enabled' => 'ci_',
|
||||
'forward_deployment_rollback_allowed' => 'ci_',
|
||||
'keep_latest_artifact' => '',
|
||||
'restrict_user_defined_variables' => '',
|
||||
'pipeline_variables_minimum_override_role' => 'ci_',
|
||||
'runner_token_expiration_interval' => '',
|
||||
'separated_caches' => 'ci_',
|
||||
|
|
|
|||
|
|
@ -1028,79 +1028,43 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
|
|||
context 'when `pipeline_variables_minimum_override_role` is defined' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
where(:user_role, :admin_mode, :minimum_role, :restrict_variables, :allowed) do
|
||||
:developer | false | :no_one_allowed | true | false
|
||||
:maintainer | false | :no_one_allowed | true | false
|
||||
:owner | false | :no_one_allowed | true | false
|
||||
:guest | false | :no_one_allowed | true | false
|
||||
:planner | false | :no_one_allowed | true | false
|
||||
:reporter | false | :no_one_allowed | true | false
|
||||
:anonymous | false | :no_one_allowed | true | false
|
||||
:developer | false | :developer | true | true
|
||||
:maintainer | false | :developer | true | true
|
||||
:owner | false | :developer | true | true
|
||||
:guest | false | :developer | true | true
|
||||
:planner | false | :developer | true | true
|
||||
:reporter | false | :developer | true | true
|
||||
:anonymous | false | :developer | true | true
|
||||
:developer | false | :maintainer | true | false
|
||||
:maintainer | false | :maintainer | true | true
|
||||
:owner | false | :maintainer | true | true
|
||||
:guest | false | :maintainer | true | false
|
||||
:planner | false | :maintainer | true | false
|
||||
:reporter | false | :maintainer | true | false
|
||||
:anonymous | false | :maintainer | true | false
|
||||
:developer | false | :owner | true | false
|
||||
:maintainer | false | :owner | true | false
|
||||
:owner | false | :owner | true | true
|
||||
:guest | false | :owner | true | false
|
||||
:planner | false | :owner | true | false
|
||||
:reporter | false | :owner | true | false
|
||||
:anonymous | false | :owner | true | false
|
||||
:developer | false | :no_one_allowed | false | true
|
||||
:maintainer | false | :no_one_allowed | false | true
|
||||
:owner | false | :no_one_allowed | false | true
|
||||
:guest | false | :no_one_allowed | false | true
|
||||
:planner | false | :no_one_allowed | false | true
|
||||
:reporter | false | :no_one_allowed | false | true
|
||||
:anonymous | false | :no_one_allowed | false | true
|
||||
:developer | false | :developer | false | true
|
||||
:maintainer | false | :developer | false | true
|
||||
:owner | false | :developer | false | true
|
||||
:guest | false | :developer | false | true
|
||||
:planner | false | :developer | false | true
|
||||
:reporter | false | :developer | false | true
|
||||
:anonymous | false | :developer | false | true
|
||||
:developer | false | :maintainer | false | true
|
||||
:maintainer | false | :maintainer | false | true
|
||||
:owner | false | :maintainer | false | true
|
||||
:guest | false | :maintainer | false | true
|
||||
:planner | false | :maintainer | false | true
|
||||
:reporter | false | :maintainer | false | true
|
||||
:anonymous | false | :maintainer | false | true
|
||||
:developer | false | :owner | false | true
|
||||
:maintainer | false | :owner | false | true
|
||||
:owner | false | :owner | false | true
|
||||
:guest | false | :owner | false | true
|
||||
:planner | false | :owner | false | true
|
||||
:reporter | false | :owner | false | true
|
||||
:anonymous | false | :owner | false | true
|
||||
:admin | false | :no_one_allowed | false | true
|
||||
:admin | false | :owner | false | true
|
||||
:admin | false | :maintainer | false | true
|
||||
:admin | false | :developer | false | true
|
||||
:admin | false | :no_one_allowed | true | false
|
||||
:admin | false | :owner | true | false
|
||||
:admin | false | :maintainer | true | false
|
||||
:admin | false | :developer | true | true
|
||||
:admin | true | :no_one_allowed | false | true
|
||||
:admin | true | :developer | false | true
|
||||
:admin | true | :maintainer | false | true
|
||||
:admin | true | :owner | false | true
|
||||
:admin | true | :no_one_allowed | true | false
|
||||
:admin | true | :developer | true | true
|
||||
:admin | true | :maintainer | true | true
|
||||
:admin | true | :owner | true | true
|
||||
where(:user_role, :admin_mode, :minimum_role, :allowed) do
|
||||
:developer | false | :no_one_allowed | false
|
||||
:maintainer | false | :no_one_allowed | false
|
||||
:owner | false | :no_one_allowed | false
|
||||
:guest | false | :no_one_allowed | false
|
||||
:planner | false | :no_one_allowed | false
|
||||
:reporter | false | :no_one_allowed | false
|
||||
:anonymous | false | :no_one_allowed | false
|
||||
:developer | false | :developer | true
|
||||
:maintainer | false | :developer | true
|
||||
:owner | false | :developer | true
|
||||
:guest | false | :developer | true
|
||||
:planner | false | :developer | true
|
||||
:reporter | false | :developer | true
|
||||
:anonymous | false | :developer | true
|
||||
:developer | false | :maintainer | false
|
||||
:maintainer | false | :maintainer | true
|
||||
:owner | false | :maintainer | true
|
||||
:guest | false | :maintainer | false
|
||||
:planner | false | :maintainer | false
|
||||
:reporter | false | :maintainer | false
|
||||
:anonymous | false | :maintainer | false
|
||||
:developer | false | :owner | false
|
||||
:maintainer | false | :owner | false
|
||||
:owner | false | :owner | true
|
||||
:guest | false | :owner | false
|
||||
:planner | false | :owner | false
|
||||
:reporter | false | :owner | false
|
||||
:anonymous | false | :owner | false
|
||||
:admin | false | :no_one_allowed | false
|
||||
:admin | false | :owner | false
|
||||
:admin | false | :maintainer | false
|
||||
:admin | false | :developer | true
|
||||
:admin | true | :no_one_allowed | false
|
||||
:admin | true | :developer | true
|
||||
:admin | true | :maintainer | true
|
||||
:admin | true | :owner | true
|
||||
end
|
||||
with_them do
|
||||
let(:current_user) { public_send(user_role) }
|
||||
|
|
@ -1108,7 +1072,6 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
|
|||
before do
|
||||
ci_cd_settings = project.ci_cd_settings
|
||||
ci_cd_settings[:pipeline_variables_minimum_override_role] = minimum_role
|
||||
ci_cd_settings[:restrict_user_defined_variables] = restrict_variables
|
||||
ci_cd_settings.save!
|
||||
|
||||
enable_admin_mode!(current_user) if admin_mode
|
||||
|
|
@ -1130,7 +1093,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
|
|||
|
||||
context 'when project allows user defined variables' do
|
||||
before do
|
||||
project.update!(restrict_user_defined_variables: false)
|
||||
project.update!(ci_pipeline_variables_minimum_override_role: :developer)
|
||||
end
|
||||
|
||||
it { is_expected.to be_allowed(:set_pipeline_variables) }
|
||||
|
|
@ -1150,7 +1113,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
|
|||
|
||||
context 'when project allows user defined variables' do
|
||||
before do
|
||||
project.update!(restrict_user_defined_variables: false)
|
||||
project.update!(ci_pipeline_variables_minimum_override_role: :developer)
|
||||
end
|
||||
|
||||
it { is_expected.to be_allowed(:set_pipeline_variables) }
|
||||
|
|
|
|||
|
|
@ -799,7 +799,7 @@ RSpec.describe API::Ci::PipelineSchedules, feature_category: :continuous_integra
|
|||
|
||||
context 'when project does not restrict use of user defined variables' do
|
||||
before do
|
||||
project.update!(restrict_user_defined_variables: false)
|
||||
project.update!(ci_pipeline_variables_minimum_override_role: :developer)
|
||||
end
|
||||
|
||||
context 'as developer' do
|
||||
|
|
@ -931,7 +931,7 @@ RSpec.describe API::Ci::PipelineSchedules, feature_category: :continuous_integra
|
|||
|
||||
context 'when project does not restrict use of user defined variables' do
|
||||
before do
|
||||
project.update!(restrict_user_defined_variables: false)
|
||||
project.update!(ci_pipeline_variables_minimum_override_role: :developer)
|
||||
end
|
||||
|
||||
context 'as developer' do
|
||||
|
|
@ -1044,7 +1044,7 @@ RSpec.describe API::Ci::PipelineSchedules, feature_category: :continuous_integra
|
|||
|
||||
context 'when project does not restrict use of user defined variables' do
|
||||
before do
|
||||
project.update!(restrict_user_defined_variables: false)
|
||||
project.update!(ci_pipeline_variables_minimum_override_role: :developer)
|
||||
end
|
||||
|
||||
context 'as developer' do
|
||||
|
|
|
|||
|
|
@ -65,12 +65,11 @@ RSpec.describe 'Getting Ci Cd Setting', feature_category: :continuous_integratio
|
|||
|
||||
describe '#pipelineVariablesMinimumOverrideRole' do
|
||||
before do
|
||||
project.ci_pipeline_variables_minimum_override_role = :no_one_allowed
|
||||
project.restrict_user_defined_variables = false
|
||||
project.ci_pipeline_variables_minimum_override_role = :developer
|
||||
project.save!
|
||||
end
|
||||
|
||||
context 'when restrict_user_defined_variables is disabled' do
|
||||
context 'when restrict_user_defined_variables is disabled via developer role' do
|
||||
it 'fetches according translation layer' do
|
||||
expect(settings_data['pipelineVariablesMinimumOverrideRole']).to eql('developer')
|
||||
end
|
||||
|
|
|
|||
|
|
@ -228,15 +228,15 @@ RSpec.describe 'ProjectCiCdSettingsUpdate', feature_category: :continuous_integr
|
|||
end
|
||||
|
||||
before do
|
||||
override_role = initial_restrict_user_defined_variables ? 'no_one_allowed' : 'developer'
|
||||
project.ci_cd_settings.update!(
|
||||
pipeline_variables_minimum_override_role: 'no_one_allowed',
|
||||
restrict_user_defined_variables: initial_restrict_user_defined_variables
|
||||
pipeline_variables_minimum_override_role: override_role
|
||||
)
|
||||
end
|
||||
|
||||
specify do
|
||||
expect { post_graphql_mutation(mutation, current_user: maintainer) }.to(
|
||||
change { project.reload.restrict_user_defined_variables }
|
||||
change { project.reload.restrict_user_defined_variables? }
|
||||
.from(false)
|
||||
.to(true)
|
||||
)
|
||||
|
|
@ -257,7 +257,7 @@ RSpec.describe 'ProjectCiCdSettingsUpdate', feature_category: :continuous_integr
|
|||
with_them do
|
||||
specify do
|
||||
expect { post_graphql_mutation(mutation, current_user: maintainer) }.not_to(
|
||||
change { project.reload.restrict_user_defined_variables }
|
||||
change { project.reload.restrict_user_defined_variables? }
|
||||
.from(initial_restrict_user_defined_variables)
|
||||
)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -116,6 +116,9 @@ ci_cd_settings:
|
|||
separated_caches: ci_separated_caches
|
||||
allow_fork_pipelines_to_run_in_parent_project: ci_allow_fork_pipelines_to_run_in_parent_project
|
||||
delete_pipelines_in_seconds: ci_delete_pipelines_in_seconds
|
||||
computed_attributes:
|
||||
- restrict_user_defined_variables
|
||||
|
||||
|
||||
build_import_state: # import_state
|
||||
unexposed_attributes:
|
||||
|
|
|
|||
|
|
@ -4516,11 +4516,6 @@ RSpec.describe API::Projects, :aggregate_failures, feature_category: :groups_and
|
|||
end
|
||||
|
||||
context 'and resrict_user_defined_variables is true' do
|
||||
before do
|
||||
ci_cd_settings.restrict_user_defined_variables = true
|
||||
ci_cd_settings.save!
|
||||
end
|
||||
|
||||
context 'and current user is maintainer' do
|
||||
let_it_be(:current_user) { user2 }
|
||||
|
||||
|
|
@ -4529,7 +4524,7 @@ RSpec.describe API::Projects, :aggregate_failures, feature_category: :groups_and
|
|||
|
||||
expect do
|
||||
put api("/projects/#{project3.id}", current_user), params: project_param
|
||||
end.to change { ci_cd_settings.reload.restrict_user_defined_variables }.from(true).to(false)
|
||||
end.to change { ci_cd_settings.reload.restrict_user_defined_variables? }.from(true).to(false)
|
||||
.and change { ci_cd_settings.pipeline_variables_minimum_override_role }.from('maintainer').to('developer')
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
|
|
@ -4540,69 +4535,61 @@ RSpec.describe API::Projects, :aggregate_failures, feature_category: :groups_and
|
|||
end
|
||||
end
|
||||
|
||||
context 'when ci_pipeline_variables_minimum_override_role is owner' do
|
||||
context 'when ci_pipeline_variables_minimum_override_role is developer' do
|
||||
let(:ci_cd_settings) { project3.ci_cd_settings }
|
||||
|
||||
before do
|
||||
project3.add_maintainer(user2)
|
||||
ci_cd_settings.pipeline_variables_minimum_override_role = 'owner'
|
||||
ci_cd_settings.pipeline_variables_minimum_override_role = 'developer'
|
||||
ci_cd_settings.save!
|
||||
end
|
||||
|
||||
context 'and resrict_user_defined_variables is false' do
|
||||
before do
|
||||
ci_cd_settings.restrict_user_defined_variables = false
|
||||
ci_cd_settings.save!
|
||||
context 'and current user is maintainer' do
|
||||
let_it_be(:current_user) { user2 }
|
||||
|
||||
it 'accepts to change restrict_user_defined_variables' do
|
||||
project_param = { restrict_user_defined_variables: true }
|
||||
|
||||
put api("/projects/#{project3.id}", current_user), params: project_param
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
|
||||
context 'and current user is maintainer' do
|
||||
let_it_be(:current_user) { user2 }
|
||||
it 'accepts to change ci_pipeline_variables_minimum_override_role' do
|
||||
project_param = { ci_pipeline_variables_minimum_override_role: 'developer' }
|
||||
|
||||
it 'accepts to change restrict_user_defined_variables' do
|
||||
project_param = { restrict_user_defined_variables: true }
|
||||
put api("/projects/#{project3.id}", current_user), params: project_param
|
||||
|
||||
put api("/projects/#{project3.id}", current_user), params: project_param
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
end
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
context 'and current user is owner' do
|
||||
let_it_be(:current_user) { user }
|
||||
|
||||
it 'accepts to change ci_pipeline_variables_minimum_override_role' do
|
||||
project_param = { ci_pipeline_variables_minimum_override_role: 'developer' }
|
||||
it 'successfully changes restrict_user_defined_variables' do
|
||||
project_param = { restrict_user_defined_variables: true }
|
||||
|
||||
put api("/projects/#{project3.id}", current_user), params: project_param
|
||||
put api("/projects/#{project3.id}", current_user), params: project_param
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
|
||||
context 'and current user is owner' do
|
||||
let_it_be(:current_user) { user }
|
||||
it 'successfully changes ci_pipeline_variables_minimum_override_role' do
|
||||
project_param = { ci_pipeline_variables_minimum_override_role: 'developer' }
|
||||
|
||||
it 'successfully changes restrict_user_defined_variables' do
|
||||
project_param = { restrict_user_defined_variables: true }
|
||||
put api("/projects/#{project3.id}", current_user), params: project_param
|
||||
|
||||
put api("/projects/#{project3.id}", current_user), params: project_param
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
|
||||
it 'successfully changes ci_pipeline_variables_minimum_override_role' do
|
||||
project_param = { ci_pipeline_variables_minimum_override_role: 'developer' }
|
||||
|
||||
put api("/projects/#{project3.id}", current_user), params: project_param
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when ci_pipeline_variables_minimum_override_role is set to maintainer' do
|
||||
context 'when ci_pipeline_variables_minimum_override_role is set to developer' do
|
||||
before do
|
||||
project3.add_maintainer(user2)
|
||||
ci_cd_settings = project3.ci_cd_settings
|
||||
ci_cd_settings.pipeline_variables_minimum_override_role = 'maintainer'
|
||||
ci_cd_settings.restrict_user_defined_variables = false
|
||||
ci_cd_settings.pipeline_variables_minimum_override_role = 'developer'
|
||||
ci_cd_settings.save!
|
||||
end
|
||||
|
||||
|
|
@ -4618,7 +4605,7 @@ RSpec.describe API::Projects, :aggregate_failures, feature_category: :groups_and
|
|||
end
|
||||
|
||||
it 'successfully changes ci_pipeline_variables_minimum_override_role' do
|
||||
project_param = { ci_pipeline_variables_minimum_override_role: 'developer' }
|
||||
project_param = { ci_pipeline_variables_minimum_override_role: 'maintainer' }
|
||||
|
||||
put api("/projects/#{project3.id}", current_user), params: project_param
|
||||
|
||||
|
|
|
|||
|
|
@ -523,8 +523,7 @@ RSpec.describe Ci::CreateDownstreamPipelineService, '#execute', feature_category
|
|||
before do
|
||||
bridge.yaml_variables = [{ key: 'BRIDGE', value: '$PIPELINE_VARIABLE-var', public: true }]
|
||||
|
||||
upstream_pipeline.project.update!(restrict_user_defined_variables: true,
|
||||
ci_pipeline_variables_minimum_override_role: :maintainer)
|
||||
upstream_pipeline.project.update!(ci_pipeline_variables_minimum_override_role: :maintainer)
|
||||
end
|
||||
|
||||
it 'creates a new pipeline allowing variables to be passed downstream' do
|
||||
|
|
@ -753,8 +752,7 @@ RSpec.describe Ci::CreateDownstreamPipelineService, '#execute', feature_category
|
|||
|
||||
context 'when downstream project does not allow user-defined variables for multi-project pipelines' do
|
||||
before do
|
||||
downstream_project.update!(restrict_user_defined_variables: true,
|
||||
ci_pipeline_variables_minimum_override_role: :maintainer)
|
||||
downstream_project.update!(ci_pipeline_variables_minimum_override_role: :maintainer)
|
||||
end
|
||||
|
||||
it 'does not create a new pipeline' do
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ RSpec.describe Ci::PipelineSchedules::VariablesCreateService, feature_category:
|
|||
subject(:service) { described_class.new(pipeline_schedule, developer, {}) }
|
||||
|
||||
before do
|
||||
project.update!(restrict_user_defined_variables: true)
|
||||
project.update!(ci_pipeline_variables_minimum_override_role: :maintainer)
|
||||
end
|
||||
|
||||
it 'returns ServiceResponse.error' do
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ RSpec.describe Ci::PipelineSchedules::VariablesUpdateService, feature_category:
|
|||
subject(:service) { described_class.new(pipeline_schedule_variable, developer, {}) }
|
||||
|
||||
before do
|
||||
project.update!(restrict_user_defined_variables: true)
|
||||
project.update!(ci_pipeline_variables_minimum_override_role: :maintainer)
|
||||
end
|
||||
|
||||
it 'returns ServiceResponse.error' do
|
||||
|
|
|
|||
|
|
@ -99,8 +99,7 @@ RSpec.describe Ci::PlayBuildService, '#execute', feature_category: :continuous_i
|
|||
|
||||
context 'when user defined variables are restricted' do
|
||||
before do
|
||||
project.update!(restrict_user_defined_variables: true,
|
||||
ci_pipeline_variables_minimum_override_role: :maintainer)
|
||||
project.update!(ci_pipeline_variables_minimum_override_role: :maintainer)
|
||||
end
|
||||
|
||||
context 'when user is maintainer' do
|
||||
|
|
|
|||
|
|
@ -139,4 +139,32 @@ RSpec.describe MergeRequests::Mergeability::CheckLfsFileLocksService, feature_ca
|
|||
it { expect(cache_key).to eq('inactive_lfs_file_locks_mergeability_check') }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_lfs_file_locks?' do
|
||||
context 'when lfs_file_locks association is not loaded' do
|
||||
before do
|
||||
allow(project.lfs_file_locks).to receive(:loaded?).and_return(false)
|
||||
allow(project.lfs_file_locks).to receive(:exists?)
|
||||
end
|
||||
|
||||
it 'calls exists?' do
|
||||
check_lfs_file_locks.has_lfs_file_locks?
|
||||
|
||||
expect(project.lfs_file_locks).to have_received(:exists?)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when lfs_file_locks association is loaded' do
|
||||
before do
|
||||
allow(project.lfs_file_locks).to receive(:loaded?).and_return(true)
|
||||
allow(project.lfs_file_locks).to receive(:any?)
|
||||
end
|
||||
|
||||
it 'calls any?' do
|
||||
check_lfs_file_locks.has_lfs_file_locks?
|
||||
|
||||
expect(project.lfs_file_locks).to have_received(:any?)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -38,21 +38,18 @@ RSpec.describe Projects::UpdateService, feature_category: :groups_and_projects d
|
|||
context 'when changing restrict_user_defined_variables' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
where(:current_user_role, :project_minimum_role, :from_value, :to_value, :expected_value, :expected_role, :status) do
|
||||
:owner | :developer | true | false | false | :developer | :success
|
||||
:owner | :maintainer | true | false | false | :developer | :success
|
||||
:owner | :developer | false | true | true | :maintainer | :success
|
||||
:owner | :maintainer | false | true | true | :maintainer | :success
|
||||
:maintainer | :developer | true | false | false | :developer | :success
|
||||
:maintainer | :maintainer | true | false | false | :developer | :success
|
||||
:maintainer | :owner | true | false | true | :owner | :api_error
|
||||
:maintainer | :owner | false | true | true | :owner | :success
|
||||
:maintainer | :owner | true | true | true | :owner | :success
|
||||
:developer | :owner | true | false | true | :owner | :api_error
|
||||
:developer | :developer | true | false | false | :developer | :success
|
||||
:developer | :maintainer | true | false | true | :maintainer | :api_error
|
||||
:developer | :maintainer | false | true | false | :developer | :api_error
|
||||
:guest | :developer | false | true | false | :developer | :api_error
|
||||
where(:current_user_role, :project_minimum_role, :to_value, :expected_value, :expected_role, :status) do
|
||||
:owner | :maintainer | false | false | :developer | :success
|
||||
:owner | :developer | true | true | :maintainer | :success
|
||||
:maintainer | :maintainer | false | false | :developer | :success
|
||||
:maintainer | :maintainer | false | false | :developer | :success
|
||||
:maintainer | :owner | false | true | :owner | :api_error
|
||||
:maintainer | :developer | true | true | :maintainer | :success
|
||||
:maintainer | :owner | true | true | :owner | :success
|
||||
:developer | :owner | false | true | :owner | :api_error
|
||||
:developer | :maintainer | false | true | :maintainer | :api_error
|
||||
:developer | :developer | true | false | :developer | :api_error
|
||||
:guest | :developer | true | false | :developer | :api_error
|
||||
end
|
||||
|
||||
with_them do
|
||||
|
|
@ -66,7 +63,6 @@ RSpec.describe Projects::UpdateService, feature_category: :groups_and_projects d
|
|||
|
||||
ci_cd_settings = project.ci_cd_settings
|
||||
ci_cd_settings[:pipeline_variables_minimum_override_role] = project_minimum_role
|
||||
ci_cd_settings[:restrict_user_defined_variables] = from_value
|
||||
ci_cd_settings.save!
|
||||
end
|
||||
|
||||
|
|
@ -75,7 +71,7 @@ RSpec.describe Projects::UpdateService, feature_category: :groups_and_projects d
|
|||
expect(result[:status]).to eq(status)
|
||||
|
||||
project.reload
|
||||
expect(project.restrict_user_defined_variables).to eq(expected_value)
|
||||
expect(project.restrict_user_defined_variables?).to eq(expected_value)
|
||||
expect(project.ci_pipeline_variables_minimum_override_role).to eq(expected_role.to_s)
|
||||
end
|
||||
end
|
||||
|
|
@ -84,18 +80,16 @@ RSpec.describe Projects::UpdateService, feature_category: :groups_and_projects d
|
|||
context 'when changing ci_pipeline_variables_minimum_override_role' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
where(:current_user_role, :restrict_user_defined_variables, :from_value, :to_value, :status) do
|
||||
:owner | true | :owner | :developer | :success
|
||||
:owner | true | :owner | :maintainer | :success
|
||||
:owner | true | :developer | :maintainer | :success
|
||||
:owner | true | :maintainer | :owner | :success
|
||||
:maintainer | true | :owner | :developer | :api_error
|
||||
:maintainer | true | :owner | :maintainer | :api_error
|
||||
:maintainer | true | :developer | :maintainer | :success
|
||||
:maintainer | true | :maintainer | :owner | :api_error
|
||||
:owner | false | :owner | :maintainer | :success
|
||||
:maintainer | false | :owner | :developer | :success
|
||||
:maintainer | false | :maintainer | :owner | :api_error
|
||||
where(:current_user_role, :from_value, :to_value, :status) do
|
||||
:owner | :owner | :developer | :success
|
||||
:owner | :owner | :maintainer | :success
|
||||
:owner | :developer | :maintainer | :success
|
||||
:owner | :maintainer | :owner | :success
|
||||
:maintainer | :owner | :developer | :api_error
|
||||
:maintainer | :owner | :maintainer | :api_error
|
||||
:maintainer | :developer | :maintainer | :success
|
||||
:maintainer | :maintainer | :owner | :api_error
|
||||
:developer | :maintainer | :owner | :api_error
|
||||
end
|
||||
|
||||
with_them do
|
||||
|
|
@ -108,7 +102,6 @@ RSpec.describe Projects::UpdateService, feature_category: :groups_and_projects d
|
|||
|
||||
ci_cd_settings = project.ci_cd_settings
|
||||
ci_cd_settings[:pipeline_variables_minimum_override_role] = from_value
|
||||
ci_cd_settings[:restrict_user_defined_variables] = restrict_user_defined_variables
|
||||
ci_cd_settings.save!
|
||||
end
|
||||
|
||||
|
|
@ -121,16 +114,16 @@ RSpec.describe Projects::UpdateService, feature_category: :groups_and_projects d
|
|||
context 'when changing both restrict_user_defined_variables and ci_pipeline_variables_minimum_override_role' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
where(:current_user_role, :from_restrict, :to_restrict, :from_role, :to_role, :expected_restrict, :expected_role, :status) do
|
||||
:owner | true | false | :owner | :developer | false | :developer | :success
|
||||
:owner | true | false | :owner | :maintainer | false | :developer | :success
|
||||
:owner | false | true | :developer | :maintainer | true | :maintainer | :success
|
||||
:owner | false | true | :maintainer | :developer | false | :developer | :success
|
||||
:maintainer | true | false | :owner | :developer | true | :owner | :api_error
|
||||
:maintainer | false | true | :developer | :maintainer | true | :maintainer | :success
|
||||
:maintainer | false | true | :maintainer | :developer | false | :developer | :success
|
||||
:developer | true | false | :maintainer | :owner | true | :maintainer | :api_error
|
||||
:developer | false | true | :owner | :maintainer | false | :developer | :api_error
|
||||
where(:current_user_role, :to_restrict, :from_role, :to_role, :expected_restrict, :expected_role, :status) do
|
||||
:owner | false | :owner | :developer | false | :developer | :success
|
||||
:owner | false | :owner | :maintainer | true | :maintainer | :success
|
||||
:owner | true | :developer | :maintainer | true | :maintainer | :success
|
||||
:owner | true | :maintainer | :developer | false | :developer | :success
|
||||
:maintainer | false | :owner | :developer | true | :owner | :api_error
|
||||
:maintainer | true | :developer | :maintainer | true | :maintainer | :success
|
||||
:maintainer | true | :maintainer | :developer | false | :developer | :success
|
||||
:developer | false | :maintainer | :owner | true | :maintainer | :api_error
|
||||
:developer | true | :owner | :maintainer | true | :owner | :api_error
|
||||
end
|
||||
|
||||
with_them do
|
||||
|
|
@ -143,7 +136,6 @@ RSpec.describe Projects::UpdateService, feature_category: :groups_and_projects d
|
|||
|
||||
ci_cd_settings = project.ci_cd_settings
|
||||
ci_cd_settings[:pipeline_variables_minimum_override_role] = from_role
|
||||
ci_cd_settings[:restrict_user_defined_variables] = from_restrict
|
||||
ci_cd_settings.save!
|
||||
end
|
||||
|
||||
|
|
@ -154,7 +146,7 @@ RSpec.describe Projects::UpdateService, feature_category: :groups_and_projects d
|
|||
expect(result[:status]).to eq(status)
|
||||
|
||||
project.reload
|
||||
expect(project.restrict_user_defined_variables).to eq(expected_restrict)
|
||||
expect(project.restrict_user_defined_variables?).to eq(expected_restrict)
|
||||
expect(project.ci_pipeline_variables_minimum_override_role).to eq(expected_role.to_s)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ RSpec.shared_examples 'pipeline schedules checking variables permission' do
|
|||
|
||||
context 'when restrict_user_defined_variables is true' do
|
||||
before_all do
|
||||
project.update!(restrict_user_defined_variables: true, ci_pipeline_variables_minimum_override_role: :maintainer)
|
||||
project.update!(ci_pipeline_variables_minimum_override_role: :maintainer)
|
||||
end
|
||||
|
||||
it_behaves_like 'success response with variables'
|
||||
|
|
@ -104,7 +104,7 @@ RSpec.shared_examples 'pipeline schedules checking variables permission' do
|
|||
|
||||
context 'when restrict_user_defined_variables is true' do
|
||||
before_all do
|
||||
project.update!(restrict_user_defined_variables: true)
|
||||
project.update!(ci_pipeline_variables_minimum_override_role: :maintainer)
|
||||
end
|
||||
|
||||
it_behaves_like 'success response'
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
require 'google/protobuf'
|
||||
|
||||
|
||||
descriptor_data = "\n\x0e\x63ontract.proto\"s\n\x0b\x43lientEvent\x12-\n\x0cstartRequest\x18\x01 \x01(\x0b\x32\x15.StartWorkflowRequestH\x00\x12)\n\x0e\x61\x63tionResponse\x18\x02 \x01(\x0b\x32\x0f.ActionResponseH\x00\x42\n\n\x08response\"\x8f\x02\n\x14StartWorkflowRequest\x12\x15\n\rclientVersion\x18\x01 \x01(\t\x12\x12\n\nworkflowID\x18\x02 \x01(\t\x12\x1a\n\x12workflowDefinition\x18\x03 \x01(\t\x12\x0c\n\x04goal\x18\x04 \x01(\t\x12\x18\n\x10workflowMetadata\x18\x05 \x01(\t\x12\x1a\n\x12\x63lientCapabilities\x18\x06 \x03(\t\x12 \n\x07\x63ontext\x18\x07 \x03(\x0b\x32\x0f.ContextElement\x12\x1a\n\x08mcpTools\x18\x08 \x03(\x0b\x32\x08.McpTool\x12.\n\x12\x61\x64\x64itional_context\x18\t \x03(\x0b\x32\x12.AdditionalContext\"\x9e\x01\n\x0e\x41\x63tionResponse\x12\x11\n\trequestID\x18\x01 \x01(\t\x12\x10\n\x08response\x18\x02 \x01(\t\x12/\n\x11plainTextResponse\x18\x03 \x01(\x0b\x32\x12.PlainTextResponseH\x00\x12%\n\x0chttpResponse\x18\x04 \x01(\x0b\x32\r.HttpResponseH\x00\x42\x0f\n\rresponse_type\"4\n\x11PlainTextResponse\x12\x10\n\x08response\x18\x01 \x01(\t\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"\x9c\x01\n\x0cHttpResponse\x12+\n\x07headers\x18\x01 \x03(\x0b\x32\x1a.HttpResponse.HeadersEntry\x12\x12\n\nstatusCode\x18\x02 \x01(\x05\x12\x0c\n\x04\x62ody\x18\x03 \x01(\t\x12\r\n\x05\x65rror\x18\x04 \x01(\t\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xb7\x03\n\x06\x41\x63tion\x12\x11\n\trequestID\x18\x01 \x01(\t\x12\'\n\nrunCommand\x18\x02 \x01(\x0b\x32\x11.RunCommandActionH\x00\x12)\n\x0erunHTTPRequest\x18\x03 \x01(\x0b\x32\x0f.RunHTTPRequestH\x00\x12 \n\x0brunReadFile\x18\x04 \x01(\x0b\x32\t.ReadFileH\x00\x12\"\n\x0crunWriteFile\x18\x05 \x01(\x0b\x32\n.WriteFileH\x00\x12\'\n\rrunGitCommand\x18\x06 \x01(\x0b\x32\x0e.RunGitCommandH\x00\x12 \n\x0brunEditFile\x18\x07 \x01(\x0b\x32\t.EditFileH\x00\x12\'\n\rnewCheckpoint\x18\x08 \x01(\x0b\x32\x0e.NewCheckpointH\x00\x12\'\n\rlistDirectory\x18\t \x01(\x0b\x32\x0e.ListDirectoryH\x00\x12\x15\n\x04grep\x18\n \x01(\x0b\x32\x05.GrepH\x00\x12\x1f\n\tfindFiles\x18\x0b \x01(\x0b\x32\n.FindFilesH\x00\x12!\n\nrunMCPTool\x18\x0c \x01(\x0b\x32\x0b.RunMCPToolH\x00\x42\x08\n\x06\x61\x63tion\"n\n\x10RunCommandAction\x12\x0f\n\x07program\x18\x03 \x01(\t\x12\x11\n\targuments\x18\x04 \x03(\t\x12\r\n\x05\x66lags\x18\x05 \x03(\tJ\x04\x08\x01\x10\x02J\x04\x08\x02\x10\x03R\x07\x63ommandR\x12withGitCredentials\"\x1c\n\x08ReadFile\x12\x10\n\x08\x66ilepath\x18\x01 \x01(\t\"/\n\tWriteFile\x12\x10\n\x08\x66ilepath\x18\x01 \x01(\t\x12\x10\n\x08\x63ontents\x18\x02 \x01(\t\"B\n\x08\x45\x64itFile\x12\x10\n\x08\x66ilepath\x18\x01 \x01(\t\x12\x11\n\toldString\x18\x02 \x01(\t\x12\x11\n\tnewString\x18\x03 \x01(\t\"J\n\x0eRunHTTPRequest\x12\x0e\n\x06method\x18\x01 \x01(\t\x12\x0c\n\x04path\x18\x02 \x01(\t\x12\x11\n\x04\x62ody\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x07\n\x05_body\"^\n\rRunGitCommand\x12\x0f\n\x07\x63ommand\x18\x01 \x01(\t\x12\x16\n\targuments\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x16\n\x0erepository_url\x18\x03 \x01(\tB\x0c\n\n_arguments\"2\n\x14GenerateTokenRequest\x12\x1a\n\x12workflowDefinition\x18\x01 \x01(\t\"9\n\x15GenerateTokenResponse\x12\r\n\x05token\x18\x01 \x01(\t\x12\x11\n\texpiresAt\x18\x02 \x01(\x03\"S\n\x0e\x43ontextElement\x12!\n\x04type\x18\x01 \x01(\x0e\x32\x13.ContextElementType\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x10\n\x08\x63ontents\x18\x03 \x01(\t\"Q\n\rNewCheckpoint\x12\x0e\n\x06status\x18\x01 \x01(\t\x12\x12\n\ncheckpoint\x18\x02 \x01(\t\x12\x0c\n\x04goal\x18\x03 \x01(\t\x12\x0e\n\x06\x65rrors\x18\x04 \x03(\t\"\"\n\rListDirectory\x12\x11\n\tdirectory\x18\x01 \x01(\t\"K\n\x04Grep\x12\x18\n\x10search_directory\x18\x01 \x01(\t\x12\x0f\n\x07pattern\x18\x02 \x01(\t\x12\x18\n\x10\x63\x61se_insensitive\x18\x03 \x01(\x08\"!\n\tFindFiles\x12\x14\n\x0cname_pattern\x18\x01 \x01(\t\"A\n\x07McpTool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x13\n\x0binputSchema\x18\x03 \x01(\t\"(\n\nRunMCPTool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04\x61rgs\x18\x02 \x01(\t\"\x83\x01\n\x11\x41\x64\x64itionalContext\x12\x10\n\x08\x63\x61tegory\x18\x01 \x01(\t\x12\x0f\n\x02id\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x07\x63ontent\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x15\n\x08metadata\x18\x04 \x01(\tH\x02\x88\x01\x01\x42\x05\n\x03_idB\n\n\x08_contentB\x0b\n\t_metadata*{\n\x12\x43ontextElementType\x12\x13\n\x0fUSER_PREFERENCE\x10\x00\x12\x11\n\rSELECTED_TEXT\x10\x01\x12\x08\n\x04\x46ILE\x10\x02\x12\t\n\x05ISSUE\x10\x03\x12\x11\n\rMERGE_REQUEST\x10\x04\x12\x15\n\x11PREVIOUS_WORKFLOW\x10\x05\x32{\n\x0b\x44uoWorkflow\x12,\n\x0f\x45xecuteWorkflow\x12\x0c.ClientEvent\x1a\x07.Action(\x01\x30\x01\x12>\n\rGenerateToken\x12\x15.GenerateTokenRequest\x1a\x16.GenerateTokenResponseBhZQgitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist/clients/gopb\xea\x02\x12\x44uoWorkflowServiceb\x06proto3"
|
||||
descriptor_data = "\n\x0e\x63ontract.proto\"s\n\x0b\x43lientEvent\x12-\n\x0cstartRequest\x18\x01 \x01(\x0b\x32\x15.StartWorkflowRequestH\x00\x12)\n\x0e\x61\x63tionResponse\x18\x02 \x01(\x0b\x32\x0f.ActionResponseH\x00\x42\n\n\x08response\"\xc3\x01\n\x14StartWorkflowRequest\x12\x15\n\rclientVersion\x18\x01 \x01(\t\x12\x12\n\nworkflowID\x18\x02 \x01(\t\x12\x1a\n\x12workflowDefinition\x18\x03 \x01(\t\x12\x0c\n\x04goal\x18\x04 \x01(\t\x12\x18\n\x10workflowMetadata\x18\x05 \x01(\t\x12\x1a\n\x12\x63lientCapabilities\x18\x06 \x03(\t\x12 \n\x07\x63ontext\x18\x07 \x03(\x0b\x32\x0f.ContextElement\"\x9e\x01\n\x0e\x41\x63tionResponse\x12\x11\n\trequestID\x18\x01 \x01(\t\x12\x10\n\x08response\x18\x02 \x01(\t\x12/\n\x11plainTextResponse\x18\x03 \x01(\x0b\x32\x12.PlainTextResponseH\x00\x12%\n\x0chttpResponse\x18\x04 \x01(\x0b\x32\r.HttpResponseH\x00\x42\x0f\n\rresponse_type\"4\n\x11PlainTextResponse\x12\x10\n\x08response\x18\x01 \x01(\t\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"\x9c\x01\n\x0cHttpResponse\x12+\n\x07headers\x18\x01 \x03(\x0b\x32\x1a.HttpResponse.HeadersEntry\x12\x12\n\nstatusCode\x18\x02 \x01(\x05\x12\x0c\n\x04\x62ody\x18\x03 \x01(\t\x12\r\n\x05\x65rror\x18\x04 \x01(\t\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x94\x03\n\x06\x41\x63tion\x12\x11\n\trequestID\x18\x01 \x01(\t\x12\'\n\nrunCommand\x18\x02 \x01(\x0b\x32\x11.RunCommandActionH\x00\x12)\n\x0erunHTTPRequest\x18\x03 \x01(\x0b\x32\x0f.RunHTTPRequestH\x00\x12 \n\x0brunReadFile\x18\x04 \x01(\x0b\x32\t.ReadFileH\x00\x12\"\n\x0crunWriteFile\x18\x05 \x01(\x0b\x32\n.WriteFileH\x00\x12\'\n\rrunGitCommand\x18\x06 \x01(\x0b\x32\x0e.RunGitCommandH\x00\x12 \n\x0brunEditFile\x18\x07 \x01(\x0b\x32\t.EditFileH\x00\x12\'\n\rnewCheckpoint\x18\x08 \x01(\x0b\x32\x0e.NewCheckpointH\x00\x12\'\n\rlistDirectory\x18\t \x01(\x0b\x32\x0e.ListDirectoryH\x00\x12\x15\n\x04grep\x18\n \x01(\x0b\x32\x05.GrepH\x00\x12\x1f\n\tfindFiles\x18\x0b \x01(\x0b\x32\n.FindFilesH\x00\x42\x08\n\x06\x61\x63tion\"n\n\x10RunCommandAction\x12\x0f\n\x07program\x18\x03 \x01(\t\x12\x11\n\targuments\x18\x04 \x03(\t\x12\r\n\x05\x66lags\x18\x05 \x03(\tJ\x04\x08\x01\x10\x02J\x04\x08\x02\x10\x03R\x07\x63ommandR\x12withGitCredentials\"\x1c\n\x08ReadFile\x12\x10\n\x08\x66ilepath\x18\x01 \x01(\t\"/\n\tWriteFile\x12\x10\n\x08\x66ilepath\x18\x01 \x01(\t\x12\x10\n\x08\x63ontents\x18\x02 \x01(\t\"B\n\x08\x45\x64itFile\x12\x10\n\x08\x66ilepath\x18\x01 \x01(\t\x12\x11\n\toldString\x18\x02 \x01(\t\x12\x11\n\tnewString\x18\x03 \x01(\t\"J\n\x0eRunHTTPRequest\x12\x0e\n\x06method\x18\x01 \x01(\t\x12\x0c\n\x04path\x18\x02 \x01(\t\x12\x11\n\x04\x62ody\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x07\n\x05_body\"^\n\rRunGitCommand\x12\x0f\n\x07\x63ommand\x18\x01 \x01(\t\x12\x16\n\targuments\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x16\n\x0erepository_url\x18\x03 \x01(\tB\x0c\n\n_arguments\"\x16\n\x14GenerateTokenRequest\"9\n\x15GenerateTokenResponse\x12\r\n\x05token\x18\x01 \x01(\t\x12\x11\n\texpiresAt\x18\x02 \x01(\x03\"S\n\x0e\x43ontextElement\x12!\n\x04type\x18\x01 \x01(\x0e\x32\x13.ContextElementType\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x10\n\x08\x63ontents\x18\x03 \x01(\t\"Q\n\rNewCheckpoint\x12\x0e\n\x06status\x18\x01 \x01(\t\x12\x12\n\ncheckpoint\x18\x02 \x01(\t\x12\x0c\n\x04goal\x18\x03 \x01(\t\x12\x0e\n\x06\x65rrors\x18\x04 \x03(\t\"\"\n\rListDirectory\x12\x11\n\tdirectory\x18\x01 \x01(\t\"K\n\x04Grep\x12\x18\n\x10search_directory\x18\x01 \x01(\t\x12\x0f\n\x07pattern\x18\x02 \x01(\t\x12\x18\n\x10\x63\x61se_insensitive\x18\x03 \x01(\x08\"!\n\tFindFiles\x12\x14\n\x0cname_pattern\x18\x01 \x01(\t*{\n\x12\x43ontextElementType\x12\x13\n\x0fUSER_PREFERENCE\x10\x00\x12\x11\n\rSELECTED_TEXT\x10\x01\x12\x08\n\x04\x46ILE\x10\x02\x12\t\n\x05ISSUE\x10\x03\x12\x11\n\rMERGE_REQUEST\x10\x04\x12\x15\n\x11PREVIOUS_WORKFLOW\x10\x05\x32{\n\x0b\x44uoWorkflow\x12,\n\x0f\x45xecuteWorkflow\x12\x0c.ClientEvent\x1a\x07.Action(\x01\x30\x01\x12>\n\rGenerateToken\x12\x15.GenerateTokenRequest\x1a\x16.GenerateTokenResponseBhZQgitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist/clients/gopb\xea\x02\x12\x44uoWorkflowServiceb\x06proto3"
|
||||
|
||||
pool = Google::Protobuf::DescriptorPool.generated_pool
|
||||
pool.add_serialized_file(descriptor_data)
|
||||
|
|
|
|||
Loading…
Reference in New Issue