Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-06-13 12:09:23 +00:00
parent 4badf32da7
commit 4d1b4c1cf3
69 changed files with 829 additions and 629 deletions

View File

@ -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'

View File

@ -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">

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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();
}
})();

View File

@ -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() {

View File

@ -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

View File

@ -31,11 +31,8 @@ export default {
directives: {
SafeHtml,
},
inject: ['currentUserId'],
props: {
currentUserId: {
type: String,
required: true,
},
todo: {
type: Object,
required: true,

View File

@ -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"

View File

@ -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,

View File

@ -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 } }

View File

@ -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?

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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?

View File

@ -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?

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 >}}

View File

@ -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`

View File

@ -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
---

View File

@ -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

View File

@ -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.

View File

@ -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 >}}

View File

@ -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). | |

View File

@ -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 >}}

View File

@ -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.
![Child epics roadmap](img/epic_view_roadmap_v12_9.png)
<!-- 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.

View File

@ -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 -->
---

View File

@ -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 >}}

View File

@ -285,7 +285,7 @@ To link the SAML groups:
{{< details >}}
- Offering: GitLab.com
- Offering: GitLab.com, GitLab Self-Managed
{{< /details >}}

View File

@ -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.

View File

@ -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
```

View File

@ -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

View File

@ -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' }

View File

@ -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)

View File

@ -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 ""

View File

@ -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

View File

@ -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(

View File

@ -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

View File

@ -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(

View File

@ -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

View File

@ -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 }

View File

@ -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);
});
});
});

View File

@ -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.');
});
});

View File

@ -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]);
});
});
});

View File

@ -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);
});
});
});

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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_',

View File

@ -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) }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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'

View File

@ -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)