Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
27d47e40e1
commit
184b3d4a21
|
|
@ -1 +1 @@
|
|||
v16.4.0-rc1
|
||||
v16.4.0-rc2
|
||||
|
|
|
|||
2
Gemfile
2
Gemfile
|
|
@ -41,7 +41,7 @@ gem 'sprockets', '~> 3.7.0'
|
|||
gem 'view_component', '~> 3.5.0'
|
||||
|
||||
# Supported DBs
|
||||
gem 'pg', '~> 1.5.3'
|
||||
gem 'pg', '~> 1.5.4'
|
||||
|
||||
gem 'neighbor', '~> 0.2.3'
|
||||
|
||||
|
|
|
|||
|
|
@ -443,10 +443,7 @@
|
|||
{"name":"parslet","version":"1.8.2","platform":"ruby","checksum":"08d1ab3721cd3f175bfbee8788b2ddff71f92038f2d69bd65454c22bb9fbd98a"},
|
||||
{"name":"pastel","version":"0.8.0","platform":"ruby","checksum":"481da9fb7d2f6e6b1a08faf11fa10363172dc40fd47848f096ae21209f805a75"},
|
||||
{"name":"peek","version":"1.1.0","platform":"ruby","checksum":"d6501ead8cde46d8d8ed0d59eb6f0ba713d0a41c11a2c4a81447b2dce37b3ecc"},
|
||||
{"name":"pg","version":"1.5.3","platform":"ruby","checksum":"6b9ee5e2d5aee975588232c41f8203e766157cf71dba54ee85b343a45ced9bfd"},
|
||||
{"name":"pg","version":"1.5.3","platform":"x64-mingw-ucrt","checksum":"1f2a6b2afaf0ccb8afe8b6a00131bce8151fbd6e8826b2d944288f6f2b615389"},
|
||||
{"name":"pg","version":"1.5.3","platform":"x64-mingw32","checksum":"ab7f5f3020323094a2b16f9638166b04c103e152a9079a1b8e795f4bf79765e0"},
|
||||
{"name":"pg","version":"1.5.3","platform":"x86-mingw32","checksum":"aa6ddda9887462d30a6d49d875eb9d27fca8cdb7185103b650e7351b38f15ddf"},
|
||||
{"name":"pg","version":"1.5.4","platform":"ruby","checksum":"04f7b247151c639a0b955d8e5a9a41541343f4640aa3c2bdf749a872c339d25d"},
|
||||
{"name":"pg_query","version":"4.2.3","platform":"ruby","checksum":"1cc9955c7bce8e51e1abc11f1952e3d9d0f1cd4c16c58c56ec75d5aaf1cfd697"},
|
||||
{"name":"plist","version":"3.6.0","platform":"ruby","checksum":"f468bcf6b72ec6d1585ed6744eb4817c1932a5bf91895ed056e69b7f12ca10f2"},
|
||||
{"name":"png_quantizator","version":"0.2.1","platform":"ruby","checksum":"6023d4d064125c3a7e02929c95b7320ed6ac0d7341f9e8de0c9ea6576ef3106b"},
|
||||
|
|
|
|||
|
|
@ -1190,7 +1190,7 @@ GEM
|
|||
tty-color (~> 0.5)
|
||||
peek (1.1.0)
|
||||
railties (>= 4.0.0)
|
||||
pg (1.5.3)
|
||||
pg (1.5.4)
|
||||
pg_query (4.2.3)
|
||||
google-protobuf (>= 3.22.3)
|
||||
plist (3.6.0)
|
||||
|
|
@ -1942,7 +1942,7 @@ DEPENDENCIES
|
|||
parser (~> 3.2, >= 3.2.2.3)
|
||||
parslet (~> 1.8)
|
||||
peek (~> 1.1)
|
||||
pg (~> 1.5.3)
|
||||
pg (~> 1.5.4)
|
||||
pg_query (~> 4.2.3)
|
||||
png_quantizator (~> 0.2.1)
|
||||
premailer-rails (~> 1.10.3)
|
||||
|
|
|
|||
|
|
@ -43,15 +43,6 @@ export default {
|
|||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
parentWorkItemId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
workItemType: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
childPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import {
|
|||
WORK_ITEM_TYPE_VALUE_ISSUE,
|
||||
WORK_ITEM_TYPE_VALUE_OBJECTIVE,
|
||||
WIDGET_TYPE_NOTES,
|
||||
WIDGET_TYPE_LINKED_ITEMS,
|
||||
} from '../constants';
|
||||
|
||||
import workItemUpdatedSubscription from '../graphql/work_item_updated.subscription.graphql';
|
||||
|
|
@ -50,6 +51,7 @@ import WorkItemNotes from './work_item_notes.vue';
|
|||
import WorkItemDetailModal from './work_item_detail_modal.vue';
|
||||
import WorkItemAwardEmoji from './work_item_award_emoji.vue';
|
||||
import WorkItemStateToggleButton from './work_item_state_toggle_button.vue';
|
||||
import WorkItemRelationships from './work_item_relationships/work_item_relationships.vue';
|
||||
|
||||
export default {
|
||||
i18n,
|
||||
|
|
@ -79,6 +81,7 @@ export default {
|
|||
AbuseCategorySelector,
|
||||
GlIntersectionObserver,
|
||||
ConfidentialityBadge,
|
||||
WorkItemRelationships,
|
||||
},
|
||||
mixins: [glFeatureFlagMixin()],
|
||||
inject: ['fullPath', 'reportAbusePath'],
|
||||
|
|
@ -259,6 +262,15 @@ export default {
|
|||
showIntersectionObserver() {
|
||||
return !this.isModal && this.workItemsMvc2Enabled;
|
||||
},
|
||||
hasLinkedWorkItems() {
|
||||
return this.glFeatures.linkedWorkItems;
|
||||
},
|
||||
workItemLinkedItems() {
|
||||
return this.isWidgetPresent(WIDGET_TYPE_LINKED_ITEMS);
|
||||
},
|
||||
showWorkItemLinkedItems() {
|
||||
return this.hasLinkedWorkItems && this.workItemLinkedItems;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.modalWorkItemIid) {
|
||||
|
|
@ -591,6 +603,11 @@ export default {
|
|||
@show-modal="openInModal"
|
||||
@addChild="$emit('addChild')"
|
||||
/>
|
||||
<work-item-relationships
|
||||
v-if="showWorkItemLinkedItems"
|
||||
:work-item-iid="workItemIid"
|
||||
:work-item-fullpath="workItem.project.fullPath"
|
||||
/>
|
||||
<work-item-notes
|
||||
v-if="workItemNotes"
|
||||
:work-item-id="workItem.id"
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import {
|
|||
WIDGET_TYPE_HIERARCHY,
|
||||
WORK_ITEM_NAME_TO_ICON_MAP,
|
||||
} from '../../constants';
|
||||
import { workItemPath } from '../../utils';
|
||||
import getWorkItemTreeQuery from '../../graphql/work_item_tree.query.graphql';
|
||||
import WorkItemLinkChildContents from '../shared/work_item_link_child_contents.vue';
|
||||
import WorkItemTreeChildren from './work_item_tree_children.vue';
|
||||
|
|
@ -90,7 +91,7 @@ export default {
|
|||
return this.isItemOpen ? __('Created') : __('Closed');
|
||||
},
|
||||
childPath() {
|
||||
return `${gon?.relative_url_root || ''}/${this.fullPath}/-/work_items/${this.childItem.iid}`;
|
||||
return workItemPath(this.fullPath, this.childItem.iid);
|
||||
},
|
||||
chevronType() {
|
||||
return this.isExpanded ? 'chevron-down' : 'chevron-right';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
<script>
|
||||
import { GlButton } from '@gitlab/ui';
|
||||
|
||||
import { s__ } from '~/locale';
|
||||
|
||||
import WidgetWrapper from '../widget_wrapper.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
WidgetWrapper,
|
||||
GlButton,
|
||||
},
|
||||
props: {
|
||||
workItemIid: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
workItemFullpath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
i18n: {
|
||||
title: s__('WorkItem|Linked Items'),
|
||||
emptyStateMessage: s__(
|
||||
"WorkItem|Link work items together to show that they're related or that one is blocking others.",
|
||||
),
|
||||
addLinkedWorkItemButtonLabel: s__('WorkItem|Add'),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<widget-wrapper class="work-item-relationships">
|
||||
<template #header>{{ $options.i18n.title }}</template>
|
||||
<template #header-right>
|
||||
<gl-button size="small" class="gl-ml-3">
|
||||
<slot name="add-button-text">{{ $options.i18n.addLinkedWorkItemButtonLabel }}</slot>
|
||||
</gl-button>
|
||||
</template>
|
||||
<template #body>
|
||||
<div class="gl-new-card-content">
|
||||
<div data-testid="links-empty">
|
||||
<p class="gl-new-card-empty">
|
||||
{{ $options.i18n.emptyStateMessage }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</widget-wrapper>
|
||||
</template>
|
||||
|
|
@ -26,6 +26,7 @@ export const WIDGET_TYPE_MILESTONE = 'MILESTONE';
|
|||
export const WIDGET_TYPE_ITERATION = 'ITERATION';
|
||||
export const WIDGET_TYPE_NOTES = 'NOTES';
|
||||
export const WIDGET_TYPE_HEALTH_STATUS = 'HEALTH_STATUS';
|
||||
export const WIDGET_TYPE_LINKED_ITEMS = 'LINKED_ITEMS';
|
||||
|
||||
export const WORK_ITEM_TYPE_ENUM_INCIDENT = 'INCIDENT';
|
||||
export const WORK_ITEM_TYPE_ENUM_ISSUE = 'ISSUE';
|
||||
|
|
|
|||
|
|
@ -100,4 +100,8 @@ fragment WorkItemWidgets on WorkItemWidget {
|
|||
... on WorkItemWidgetAwardEmoji {
|
||||
type
|
||||
}
|
||||
|
||||
... on WorkItemWidgetLinkedItems {
|
||||
type
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { joinPaths } from '~/lib/utils/url_utility';
|
||||
import {
|
||||
WIDGET_TYPE_ASSIGNEES,
|
||||
WIDGET_TYPE_HEALTH_STATUS,
|
||||
|
|
@ -42,3 +43,7 @@ export const markdownPreviewPath = (fullPath, iid) =>
|
|||
`${
|
||||
gon.relative_url_root || ''
|
||||
}/${fullPath}/preview_markdown?target_type=WorkItem&target_id=${iid}`;
|
||||
|
||||
export const workItemPath = (fullPath, workItemIid) => {
|
||||
return joinPaths(gon?.relative_url_root || '/', fullPath, '-', 'work_items', workItemIid);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ class Projects::IncidentsController < Projects::ApplicationController
|
|||
push_force_frontend_feature_flag(:work_items_mvc_2, @project&.work_items_mvc_2_feature_flag_enabled?)
|
||||
push_frontend_feature_flag(:moved_mr_sidebar, project)
|
||||
push_frontend_feature_flag(:move_close_into_dropdown, project)
|
||||
push_force_frontend_feature_flag(:linked_work_items, @project&.linked_work_items_feature_flag_enabled?)
|
||||
end
|
||||
|
||||
feature_category :incident_management
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
push_frontend_feature_flag(:epic_widget_edit_confirmation, project)
|
||||
push_frontend_feature_flag(:moved_mr_sidebar, project)
|
||||
push_frontend_feature_flag(:move_close_into_dropdown, project)
|
||||
push_force_frontend_feature_flag(:linked_work_items, project.linked_work_items_feature_flag_enabled?)
|
||||
end
|
||||
|
||||
around_action :allow_gitaly_ref_name_caching, only: [:discussions]
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ class Projects::WorkItemsController < Projects::ApplicationController
|
|||
push_force_frontend_feature_flag(:work_items_mvc, project&.work_items_mvc_feature_flag_enabled?)
|
||||
push_force_frontend_feature_flag(:work_items_mvc_2, project&.work_items_mvc_2_feature_flag_enabled?)
|
||||
push_force_frontend_feature_flag(:saved_replies, current_user)
|
||||
push_force_frontend_feature_flag(:linked_work_items, project&.linked_work_items_feature_flag_enabled?)
|
||||
end
|
||||
|
||||
feature_category :team_planning
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ class ProjectsController < Projects::ApplicationController
|
|||
push_force_frontend_feature_flag(:work_items, @project&.work_items_feature_flag_enabled?)
|
||||
push_force_frontend_feature_flag(:work_items_mvc, @project&.work_items_mvc_feature_flag_enabled?)
|
||||
push_force_frontend_feature_flag(:work_items_mvc_2, @project&.work_items_mvc_2_feature_flag_enabled?)
|
||||
push_force_frontend_feature_flag(:linked_work_items, @project&.linked_work_items_feature_flag_enabled?)
|
||||
end
|
||||
|
||||
layout :determine_layout
|
||||
|
|
|
|||
|
|
@ -130,10 +130,14 @@ module MergeRequests
|
|||
if source_branch_default? && !target_branch_specified?
|
||||
merge_request.target_branch = nil
|
||||
else
|
||||
merge_request.target_branch ||= target_project.default_branch
|
||||
merge_request.target_branch ||= get_target_branch
|
||||
end
|
||||
end
|
||||
|
||||
def get_target_branch
|
||||
target_project.default_branch
|
||||
end
|
||||
|
||||
def source_branch_specified?
|
||||
params[:source_branch].present?
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,4 +5,5 @@
|
|||
|
||||
= form_tag path do
|
||||
%input{ :name => "_method", :type => "hidden", :value => "delete" }/
|
||||
= submit_tag _('Revoke'), class: 'gl-button btn btn-danger btn-sm', aria: { label: s_('AuthorizedApplication|Revoke application') }, data: { confirm: s_('AuthorizedApplication|Are you sure you want to revoke this application?'), confirm_btn_variant: 'danger' }
|
||||
= render Pajamas::ButtonComponent.new(type: :submit, variant: :danger, size: :small, button_options: { aria: { label: s_('AuthorizedApplication|Revoke application') }, data: { confirm: s_('AuthorizedApplication|Are you sure you want to revoke this application?'), confirm_btn_variant: 'danger' } }) do
|
||||
= _('Revoke')
|
||||
|
|
|
|||
|
|
@ -74,13 +74,13 @@ four standard [pagination arguments](#connection-pagination-arguments):
|
|||
|
||||
### `Query.aiMessages`
|
||||
|
||||
Find AI messages.
|
||||
Find AI Duo Chat messages.
|
||||
|
||||
WARNING:
|
||||
**Introduced** in 16.1.
|
||||
This feature is an Experiment. It can be changed or removed at any time.
|
||||
|
||||
Returns [`AiCachedMessageTypeConnection!`](#aicachedmessagetypeconnection).
|
||||
Returns [`AiChatMessageConnection!`](#aichatmessageconnection).
|
||||
|
||||
This field returns a [connection](#connections). It accepts the
|
||||
four standard [pagination arguments](#connection-pagination-arguments):
|
||||
|
|
@ -91,7 +91,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
|
|||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="queryaimessagesrequestids"></a>`requestIds` | [`[ID!]`](#id) | Array of request IDs to fetch. |
|
||||
| <a id="queryaimessagesroles"></a>`roles` | [`[AiCachedMessageRole!]`](#aicachedmessagerole) | Array of roles to fetch. |
|
||||
| <a id="queryaimessagesroles"></a>`roles` | [`[AiChatMessageRole!]`](#aichatmessagerole) | Array of roles to fetch. |
|
||||
|
||||
### `Query.auditEventDefinitions`
|
||||
|
||||
|
|
@ -7775,28 +7775,28 @@ The edge type for [`AgentConfiguration`](#agentconfiguration).
|
|||
| <a id="agentconfigurationedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
|
||||
| <a id="agentconfigurationedgenode"></a>`node` | [`AgentConfiguration`](#agentconfiguration) | The item at the end of the edge. |
|
||||
|
||||
#### `AiCachedMessageTypeConnection`
|
||||
#### `AiChatMessageConnection`
|
||||
|
||||
The connection type for [`AiCachedMessageType`](#aicachedmessagetype).
|
||||
The connection type for [`AiChatMessage`](#aichatmessage).
|
||||
|
||||
##### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="aicachedmessagetypeconnectionedges"></a>`edges` | [`[AiCachedMessageTypeEdge]`](#aicachedmessagetypeedge) | A list of edges. |
|
||||
| <a id="aicachedmessagetypeconnectionnodes"></a>`nodes` | [`[AiCachedMessageType]`](#aicachedmessagetype) | A list of nodes. |
|
||||
| <a id="aicachedmessagetypeconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
|
||||
| <a id="aichatmessageconnectionedges"></a>`edges` | [`[AiChatMessageEdge]`](#aichatmessageedge) | A list of edges. |
|
||||
| <a id="aichatmessageconnectionnodes"></a>`nodes` | [`[AiChatMessage]`](#aichatmessage) | A list of nodes. |
|
||||
| <a id="aichatmessageconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
|
||||
|
||||
#### `AiCachedMessageTypeEdge`
|
||||
#### `AiChatMessageEdge`
|
||||
|
||||
The edge type for [`AiCachedMessageType`](#aicachedmessagetype).
|
||||
The edge type for [`AiChatMessage`](#aichatmessage).
|
||||
|
||||
##### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="aicachedmessagetypeedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
|
||||
| <a id="aicachedmessagetypeedgenode"></a>`node` | [`AiCachedMessageType`](#aicachedmessagetype) | The item at the end of the edge. |
|
||||
| <a id="aichatmessageedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
|
||||
| <a id="aichatmessageedgenode"></a>`node` | [`AiChatMessage`](#aichatmessage) | The item at the end of the edge. |
|
||||
|
||||
#### `AiMessageTypeConnection`
|
||||
|
||||
|
|
@ -12578,19 +12578,21 @@ Information about a connected Agent.
|
|||
| <a id="agentmetadatapodnamespace"></a>`podNamespace` | [`String`](#string) | Namespace of the pod running the Agent. |
|
||||
| <a id="agentmetadataversion"></a>`version` | [`String`](#string) | Agent version tag. |
|
||||
|
||||
### `AiCachedMessageType`
|
||||
### `AiChatMessage`
|
||||
|
||||
Duo Chat message.
|
||||
|
||||
#### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="aicachedmessagetypecontent"></a>`content` | [`String`](#string) | Content of the message. Can be null for failed responses. |
|
||||
| <a id="aicachedmessagetypecontenthtml"></a>`contentHtml` | [`String`](#string) | HTML content of the message. Can be null for failed responses. |
|
||||
| <a id="aicachedmessagetypeerrors"></a>`errors` | [`[String!]!`](#string) | Errors that occurred while asynchronously fetching an AI (assistant) response. |
|
||||
| <a id="aicachedmessagetypeid"></a>`id` | [`ID`](#id) | UUID of the message. |
|
||||
| <a id="aicachedmessagetyperequestid"></a>`requestId` | [`ID`](#id) | UUID of the original request message. |
|
||||
| <a id="aicachedmessagetyperole"></a>`role` | [`AiCachedMessageRole!`](#aicachedmessagerole) | Message role. |
|
||||
| <a id="aicachedmessagetypetimestamp"></a>`timestamp` | [`Time!`](#time) | Message timestamp. |
|
||||
| <a id="aichatmessagecontent"></a>`content` | [`String`](#string) | Content of the message. Can be null for failed responses. |
|
||||
| <a id="aichatmessagecontenthtml"></a>`contentHtml` | [`String`](#string) | Content of the message in HTML format. Can be null for failed responses. |
|
||||
| <a id="aichatmessageerrors"></a>`errors` | [`[String!]!`](#string) | Errors that occurred while asynchronously fetching an AI (assistant) response. |
|
||||
| <a id="aichatmessageid"></a>`id` | [`ID`](#id) | UUID of the message. |
|
||||
| <a id="aichatmessagerequestid"></a>`requestId` | [`ID`](#id) | UUID of the original request message. Shared between chat prompt and response. |
|
||||
| <a id="aichatmessagerole"></a>`role` | [`AiChatMessageRole!`](#aichatmessagerole) | Message role. |
|
||||
| <a id="aichatmessagetimestamp"></a>`timestamp` | [`Time!`](#time) | Message timestamp. |
|
||||
|
||||
### `AiMessageType`
|
||||
|
||||
|
|
@ -12615,7 +12617,7 @@ Information about a connected Agent.
|
|||
| <a id="airesponserequestid"></a>`requestId` | [`String`](#string) | ID of the original request. |
|
||||
| <a id="airesponseresponsebody"></a>`responseBody` | [`String`](#string) | Response body from AI API. |
|
||||
| <a id="airesponseresponsebodyhtml"></a>`responseBodyHtml` | [`String`](#string) | Response body HTML. |
|
||||
| <a id="airesponserole"></a>`role` | [`AiCachedMessageRole!`](#aicachedmessagerole) | Message role. |
|
||||
| <a id="airesponserole"></a>`role` | [`AiChatMessageRole!`](#aichatmessagerole) | Message role. |
|
||||
| <a id="airesponsetimestamp"></a>`timestamp` | [`Time!`](#time) | Message timestamp. |
|
||||
| <a id="airesponsetype"></a>`type` | [`String`](#string) | Message type. |
|
||||
|
||||
|
|
@ -22155,7 +22157,7 @@ Network Policies of the project.
|
|||
|
||||
WARNING:
|
||||
**Deprecated** in 14.8.
|
||||
Network policies are deprecated and will be removed in GitLab 16.0. Since GitLab 15.0 this field returns no data.
|
||||
Network policies are deprecated and will be removed in GitLab 17.0. This field returns no data in GitLab 15.0 and later.
|
||||
|
||||
Returns [`NetworkPolicyConnection`](#networkpolicyconnection).
|
||||
|
||||
|
|
@ -25976,15 +25978,15 @@ Agent token statuses.
|
|||
| <a id="agenttokenstatusactive"></a>`ACTIVE` | Active agent token. |
|
||||
| <a id="agenttokenstatusrevoked"></a>`REVOKED` | Revoked agent token. |
|
||||
|
||||
### `AiCachedMessageRole`
|
||||
### `AiChatMessageRole`
|
||||
|
||||
Roles to filter in chat message.
|
||||
|
||||
| Value | Description |
|
||||
| ----- | ----------- |
|
||||
| <a id="aicachedmessageroleassistant"></a>`ASSISTANT` | Filter only assistant messages. |
|
||||
| <a id="aicachedmessagerolesystem"></a>`SYSTEM` | Filter only system messages. |
|
||||
| <a id="aicachedmessageroleuser"></a>`USER` | Filter only user messages. |
|
||||
| <a id="aichatmessageroleassistant"></a>`ASSISTANT` | Filter only assistant messages. |
|
||||
| <a id="aichatmessagerolesystem"></a>`SYSTEM` | Filter only system messages. |
|
||||
| <a id="aichatmessageroleuser"></a>`USER` | Filter only user messages. |
|
||||
|
||||
### `AlertManagementAlertSort`
|
||||
|
||||
|
|
|
|||
|
|
@ -784,12 +784,12 @@ The `.gitlab-ci.yml` in a downstream project:
|
|||
|
||||
```yaml
|
||||
deploy:
|
||||
script: echo "Deploy to ${CI_ENVIRONMENT_NAME} for ${CI_PROJECT_ID}"
|
||||
script: echo "Deploy to ${UPSTREAM_ENVIRONMENT_NAME} for ${UPSTREAM_PROJECT_ID}"
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "pipeline" && $UPSTREAM_ENVIRONMENT_ACTION == "start"
|
||||
|
||||
stop:
|
||||
script: echo "Stop ${CI_ENVIRONMENT_NAME} for ${CI_PROJECT_ID}"
|
||||
script: echo "Stop ${UPSTREAM_ENVIRONMENT_NAME} for ${UPSTREAM_PROJECT_ID}"
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "pipeline" && $UPSTREAM_ENVIRONMENT_ACTION == "stop"
|
||||
```
|
||||
|
|
|
|||
|
|
@ -47,6 +47,9 @@ it's reset to a pristine test after each test.
|
|||
in turn causes tests that rely on the transactions on these connections to
|
||||
in turn causes tests that rely on the transactions on these connections to
|
||||
fail. The issue was fixed in this [merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/128567).
|
||||
- [Example 7](https://gitlab.com/gitlab-org/quality/engineering-productivity/master-broken-incidents/-/issues/3389#note_1534827164):
|
||||
A TCP socket used in a test was not closed before the next test, which also used
|
||||
the same port with another TCP socket.
|
||||
|
||||
### Dataset-specific
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ module BulkImports
|
|||
object.notes.each_batch(of: BATCH_SIZE) do |notes_batch|
|
||||
notes_batch.each do |note|
|
||||
note.refresh_markdown_cache!
|
||||
enum << note if object_has_reference?(note) || object_has_username?(object)
|
||||
enum << note if object_has_reference?(note) || object_has_username?(note)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -53609,6 +53609,12 @@ msgstr ""
|
|||
msgid "WorkItem|Key result"
|
||||
msgstr ""
|
||||
|
||||
msgid "WorkItem|Link work items together to show that they're related or that one is blocking others."
|
||||
msgstr ""
|
||||
|
||||
msgid "WorkItem|Linked Items"
|
||||
msgstr ""
|
||||
|
||||
msgid "WorkItem|Mark as done"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -93,8 +93,6 @@ describe('WorkItemLinkChild', () => {
|
|||
expect(findWorkItemLinkChildContents().props()).toEqual({
|
||||
childItem: workItemObjectiveWithChild,
|
||||
canUpdate: true,
|
||||
parentWorkItemId: 'gid://gitlab/WorkItem/2',
|
||||
workItemType: 'Objective',
|
||||
childPath: '/gitlab-org/gitlab-test/-/work_items/12',
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import WorkItemRelationships from '~/work_items/components/work_item_relationships/work_item_relationships.vue';
|
||||
|
||||
describe('WorkItemRelationships', () => {
|
||||
let wrapper;
|
||||
|
||||
const createComponent = async () => {
|
||||
wrapper = shallowMountExtended(WorkItemRelationships, {
|
||||
propsData: {
|
||||
workItem: {},
|
||||
workItemIid: '1',
|
||||
workItemFullpath: 'gitlab/path',
|
||||
},
|
||||
});
|
||||
|
||||
await waitForPromises();
|
||||
};
|
||||
|
||||
it('renders the component', () => {
|
||||
createComponent();
|
||||
|
||||
expect(wrapper.find('.work-item-relationships').exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { autocompleteDataSources, markdownPreviewPath } from '~/work_items/utils';
|
||||
import { autocompleteDataSources, markdownPreviewPath, workItemPath } from '~/work_items/utils';
|
||||
|
||||
describe('autocompleteDataSources', () => {
|
||||
beforeEach(() => {
|
||||
|
|
@ -25,3 +25,14 @@ describe('markdownPreviewPath', () => {
|
|||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('workItemPath', () => {
|
||||
it('returns corrrect data sources', () => {
|
||||
expect(workItemPath('project/group', '2')).toEqual('/project/group/-/work_items/2');
|
||||
});
|
||||
|
||||
it('returns corrrect data sources with relative url root', () => {
|
||||
gon.relative_url_root = '/foobar';
|
||||
expect(workItemPath('project/group', '2')).toEqual('/foobar/project/group/-/work_items/2');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ RSpec.describe BulkImports::Projects::Pipelines::ReferencesPipeline, feature_cat
|
|||
|
||||
let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
|
||||
let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
|
||||
let(:issue) { create(:issue, project: project, description: 'https://my.gitlab.com/source/full/path/-/issues/1 @old_username') }
|
||||
let(:issue) { create(:issue, project: project, description: 'https://my.gitlab.com/source/full/path/-/issues/1') }
|
||||
let(:mr) do
|
||||
create(
|
||||
:merge_request,
|
||||
|
|
@ -58,14 +58,37 @@ RSpec.describe BulkImports::Projects::Pipelines::ReferencesPipeline, feature_cat
|
|||
)
|
||||
end
|
||||
|
||||
let(:username_system_note) do
|
||||
create(
|
||||
:note,
|
||||
project: project,
|
||||
system: true,
|
||||
noteable: issue,
|
||||
note: "mentioned in merge request created by @source_username",
|
||||
note_html: 'empty'
|
||||
)
|
||||
end
|
||||
|
||||
subject(:pipeline) { described_class.new(context) }
|
||||
|
||||
before do
|
||||
project.add_owner(user)
|
||||
|
||||
allow(Gitlab::Cache::Import::Caching)
|
||||
.to receive(:values_from_hash)
|
||||
.and_return({
|
||||
'old_username' => 'new_username',
|
||||
'older_username' => 'newer_username',
|
||||
'source_username' => 'destination_username'
|
||||
})
|
||||
end
|
||||
|
||||
def create_project_data
|
||||
[issue, mr, issue_note, mr_note, system_note]
|
||||
[issue, mr, issue_note, mr_note, system_note, username_system_note]
|
||||
end
|
||||
|
||||
def create_username_project_data
|
||||
[username_system_note]
|
||||
end
|
||||
|
||||
describe '#extract' do
|
||||
|
|
@ -75,12 +98,14 @@ RSpec.describe BulkImports::Projects::Pipelines::ReferencesPipeline, feature_cat
|
|||
extracted_data = subject.extract(context)
|
||||
|
||||
expect(extracted_data).to be_instance_of(BulkImports::Pipeline::ExtractedData)
|
||||
expect(extracted_data.data).to contain_exactly(issue_note, mr, issue, mr_note)
|
||||
expect(extracted_data.data).to contain_exactly(issue, mr, issue_note, system_note, username_system_note, mr_note)
|
||||
expect(system_note.note_html).not_to eq(old_note_html)
|
||||
expect(system_note.note_html)
|
||||
.to include("class=\"gfm gfm-merge_request\">!#{mr.iid}</a>")
|
||||
.and include(project.full_path.to_s)
|
||||
.and include("@old_username")
|
||||
expect(username_system_note.note_html)
|
||||
.to include("@source_username")
|
||||
end
|
||||
|
||||
context 'when object body is nil' do
|
||||
|
|
@ -95,22 +120,13 @@ RSpec.describe BulkImports::Projects::Pipelines::ReferencesPipeline, feature_cat
|
|||
end
|
||||
|
||||
describe '#transform' do
|
||||
before do
|
||||
allow(Gitlab::Cache::Import::Caching)
|
||||
.to receive(:values_from_hash)
|
||||
.and_return({
|
||||
'old_username' => 'new_username',
|
||||
'older_username' => 'newer_username',
|
||||
'source_username' => 'destination_username'
|
||||
})
|
||||
end
|
||||
|
||||
it 'updates matching urls and usernames with new ones' do
|
||||
transformed_mr = subject.transform(context, mr)
|
||||
transformed_note = subject.transform(context, mr_note)
|
||||
transformed_issue = subject.transform(context, issue)
|
||||
transformed_issue_note = subject.transform(context, issue_note)
|
||||
transformed_system_note = subject.transform(context, system_note)
|
||||
transformed_username_system_note = subject.transform(context, username_system_note)
|
||||
|
||||
expected_url = URI('')
|
||||
expected_url.scheme = ::Gitlab.config.gitlab.https ? 'https' : 'http'
|
||||
|
|
@ -118,16 +134,17 @@ RSpec.describe BulkImports::Projects::Pipelines::ReferencesPipeline, feature_cat
|
|||
expected_url.port = ::Gitlab.config.gitlab.port
|
||||
expected_url.path = "/#{project.full_path}/-/merge_requests/#{mr.iid}"
|
||||
|
||||
expect(transformed_issue.description).not_to include("@old_username")
|
||||
expect(transformed_issue_note.note).not_to include("@older_username")
|
||||
expect(transformed_mr.description).not_to include("@source_username")
|
||||
expect(transformed_system_note.note).not_to include("@old_username")
|
||||
expect(transformed_username_system_note.note).not_to include("@source_username")
|
||||
|
||||
expect(transformed_issue.description).to eq('http://localhost:80/namespace1/project-1/-/issues/1')
|
||||
expect(transformed_mr.description).to eq("#{expected_url} @destination_username")
|
||||
expect(transformed_note.note).to eq("#{expected_url} @same_username")
|
||||
expect(transformed_issue.description).to include("@new_username")
|
||||
expect(transformed_issue_note.note).to include("@newer_username and not_a@username")
|
||||
expect(transformed_system_note.note).to eq("mentioned in merge request !#{mr.iid} created by @new_username")
|
||||
expect(transformed_username_system_note.note).to include("@destination_username")
|
||||
end
|
||||
|
||||
context 'when object does not have reference or username' do
|
||||
|
|
@ -176,16 +193,6 @@ RSpec.describe BulkImports::Projects::Pipelines::ReferencesPipeline, feature_cat
|
|||
end
|
||||
|
||||
describe '#load' do
|
||||
before do
|
||||
allow(Gitlab::Cache::Import::Caching)
|
||||
.to receive(:values_from_hash)
|
||||
.and_return({
|
||||
'old_username' => 'new_username',
|
||||
'older_username' => 'newer_username',
|
||||
'source_username' => 'destination_username'
|
||||
})
|
||||
end
|
||||
|
||||
it 'saves the object when object body changed' do
|
||||
transformed_issue = subject.transform(context, issue)
|
||||
transformed_note = subject.transform(context, mr_note)
|
||||
|
|
|
|||
Loading…
Reference in New Issue