Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-09-27 18:12:52 +00:00
parent 5ba7c90d3a
commit f5d4db8bf5
61 changed files with 453 additions and 553 deletions

View File

@ -11,7 +11,6 @@ Layout/SpaceInsideParens:
- 'spec/lib/error_tracking/sentry_client/projects_spec.rb'
- 'spec/lib/error_tracking/sentry_client/repo_spec.rb'
- 'spec/lib/feature/gitaly_spec.rb'
- 'spec/lib/gitlab/app_text_logger_spec.rb'
- 'spec/lib/gitlab/auth/o_auth/auth_hash_spec.rb'
- 'spec/lib/gitlab/ci/config/entry/reports_spec.rb'
- 'spec/lib/gitlab/ci/config/entry/trigger_spec.rb'

View File

@ -1087,7 +1087,6 @@ RSpec/FeatureCategory:
- 'ee/spec/services/boards/lists/update_service_spec.rb'
- 'ee/spec/services/boards/update_service_spec.rb'
- 'ee/spec/services/boards/user_preferences/update_service_spec.rb'
- 'ee/spec/services/branches/delete_service_spec.rb'
- 'ee/spec/services/external_status_checks/create_service_spec.rb'
- 'ee/spec/services/projects/alerting/notify_service_spec.rb'
- 'ee/spec/services/projects/cleanup_service_spec.rb'

View File

@ -1843,7 +1843,6 @@ Style/InlineDisableAnnotation:
- 'ee/spec/serializers/vulnerabilities/issue_link_entity_spec.rb'
- 'ee/spec/serializers/vulnerabilities/merge_request_link_entity_spec.rb'
- 'ee/spec/services/app_sec/fuzzing/api/ci_configuration_create_service_spec.rb'
- 'ee/spec/services/branches/delete_service_spec.rb'
- 'ee/spec/services/ee/branches/delete_service_spec.rb'
- 'ee/spec/services/ee/resource_events/change_iteration_service_spec.rb'
- 'ee/spec/services/geo/file_registry_removal_service_spec.rb'

View File

@ -23,7 +23,7 @@
{"name":"apollo_upload_server","version":"2.1.6","platform":"ruby","checksum":"dcec4072258e6518b0b82e03b485efbddde946813543c14184fc81952d6bcdb2"},
{"name":"app_store_connect","version":"0.29.0","platform":"ruby","checksum":"01d7a923825a4221892099acb5a72f86f6ee7d8aa95815d3c459ba6816ea430f"},
{"name":"arr-pm","version":"0.0.12","platform":"ruby","checksum":"fdff482f75239239201f4d667d93424412639aad0b3b0ad4d827e7c637e0ad39"},
{"name":"asciidoctor","version":"2.0.18","platform":"ruby","checksum":"bbd1e1d16deed8db94bf9624b9f4474fac32d9ca7225d377f076c08d9adde387"},
{"name":"asciidoctor","version":"2.0.23","platform":"ruby","checksum":"52208807f237dfa0ca29882f8b13d60b820496116ad191cf197ca56f2b7fddf3"},
{"name":"asciidoctor-include-ext","version":"0.4.0","platform":"ruby","checksum":"406adb9d2fbfc25536609ca13b787ed704dc06a4e49d6709b83f3bad578f7878"},
{"name":"asciidoctor-kroki","version":"0.10.0","platform":"ruby","checksum":"8e4225d88f120e2e7b5d3f5ddb67c5e69496d7344a16c57db5036ac900123062"},
{"name":"asciidoctor-plantuml","version":"0.0.16","platform":"ruby","checksum":"407e47cd1186ded5ccc75f0c812e5524c26c571d542247c5132abb8f47bd1793"},

View File

@ -316,7 +316,7 @@ GEM
activesupport (>= 6.0.0)
jwt (>= 1.4, <= 2.5.0)
arr-pm (0.0.12)
asciidoctor (2.0.18)
asciidoctor (2.0.23)
asciidoctor-include-ext (0.4.0)
asciidoctor (>= 1.5.6, < 3.0.0)
asciidoctor-kroki (0.10.0)

View File

@ -23,7 +23,7 @@
{"name":"apollo_upload_server","version":"2.1.6","platform":"ruby","checksum":"dcec4072258e6518b0b82e03b485efbddde946813543c14184fc81952d6bcdb2"},
{"name":"app_store_connect","version":"0.29.0","platform":"ruby","checksum":"01d7a923825a4221892099acb5a72f86f6ee7d8aa95815d3c459ba6816ea430f"},
{"name":"arr-pm","version":"0.0.12","platform":"ruby","checksum":"fdff482f75239239201f4d667d93424412639aad0b3b0ad4d827e7c637e0ad39"},
{"name":"asciidoctor","version":"2.0.18","platform":"ruby","checksum":"bbd1e1d16deed8db94bf9624b9f4474fac32d9ca7225d377f076c08d9adde387"},
{"name":"asciidoctor","version":"2.0.23","platform":"ruby","checksum":"52208807f237dfa0ca29882f8b13d60b820496116ad191cf197ca56f2b7fddf3"},
{"name":"asciidoctor-include-ext","version":"0.4.0","platform":"ruby","checksum":"406adb9d2fbfc25536609ca13b787ed704dc06a4e49d6709b83f3bad578f7878"},
{"name":"asciidoctor-kroki","version":"0.10.0","platform":"ruby","checksum":"8e4225d88f120e2e7b5d3f5ddb67c5e69496d7344a16c57db5036ac900123062"},
{"name":"asciidoctor-plantuml","version":"0.0.16","platform":"ruby","checksum":"407e47cd1186ded5ccc75f0c812e5524c26c571d542247c5132abb8f47bd1793"},
@ -342,7 +342,7 @@
{"name":"io-event","version":"1.6.5","platform":"ruby","checksum":"5da4c044ac5f411563da1a4743d28c8d30d7802e29370db42139a52b807b4ce2"},
{"name":"ipaddr","version":"1.2.5","platform":"ruby","checksum":"4e679c71d6d8ed99f925487082f70f9a958de155591caa0e7f6cef9aa160f17a"},
{"name":"ipaddress","version":"0.8.3","platform":"ruby","checksum":"85640c4f9194c26937afc8c78e3074a8e7c97d5d1210358d1440f01034d006f5"},
{"name":"irb","version":"1.14.0","platform":"ruby","checksum":"53d805013bbd194874b8c13a56aca6aebcd11dd79166d88724f8a434fedde615"},
{"name":"irb","version":"1.14.1","platform":"ruby","checksum":"5975003b58d36efaf492380baa982ceedf5aed36967a4d5b40996bc5c66e80f8"},
{"name":"jaeger-client","version":"1.1.0","platform":"ruby","checksum":"cb5e9b9bbee6ee8d6a82d03d947a5b04543d8c0a949c22e484254f18d8a458a8"},
{"name":"jaro_winkler","version":"1.5.6","platform":"java","checksum":"3262aea433861fec3179184e9adc1933cca8bc15665957a143b56816f1a22f74"},
{"name":"jaro_winkler","version":"1.5.6","platform":"ruby","checksum":"007db7805527ada1cc12f2547676181d63b0a504ec4dd7a9a2eb2424521ccd81"},

View File

@ -325,7 +325,7 @@ GEM
activesupport (>= 6.0.0)
jwt (>= 1.4, <= 2.5.0)
arr-pm (0.0.12)
asciidoctor (2.0.18)
asciidoctor (2.0.23)
asciidoctor-include-ext (0.4.0)
asciidoctor (>= 1.5.6, < 3.0.0)
asciidoctor-kroki (0.10.0)
@ -1022,7 +1022,7 @@ GEM
io-event (1.6.5)
ipaddr (1.2.5)
ipaddress (0.8.3)
irb (1.14.0)
irb (1.14.1)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
jaeger-client (1.1.0)

View File

@ -91,6 +91,11 @@ export default {
// Don't do anything if this happened on a no trigger element
if (e.target.closest('.js-no-trigger')) return;
if (e.target.closest('.js-no-trigger-title') && (e.ctrlKey || e.metaKey || e.button === 1)) {
return;
}
e.preventDefault();
const isMultiSelect = e.ctrlKey || e.metaKey;
if (isMultiSelect && gon?.features?.boardMultiSelect) {
this.toggleBoardItemMultiSelection(this.item);

View File

@ -3,6 +3,7 @@ import { GlLabel, GlTooltipDirective, GlIcon, GlLoadingIcon } from '@gitlab/ui';
import { sortBy } from 'lodash';
import boardCardInner from 'ee_else_ce/boards/mixins/board_card_inner';
import { isScopedLabel, convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { updateHistory, queryToObject } from '~/lib/utils/url_utility';
import { sprintf, __, n__ } from '~/locale';
import isShowingLabelsQuery from '~/graphql_shared/client/is_showing_labels.query.graphql';
@ -36,7 +37,7 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
mixins: [boardCardInner],
mixins: [boardCardInner, glFeatureFlagsMixin()],
inject: [
'allowSubEpics',
'rootPath',
@ -260,8 +261,13 @@ export default {
<a
:href="item.path || item.webUrl || ''"
:title="item.title"
:class="{ '!gl-text-gray-400': isLoading }"
class="js-no-trigger gl-text-primary hover:gl-text-gray-900"
:class="{
'!gl-text-gray-400': isLoading,
'js-no-trigger': !glFeatures.issuesListDrawer,
'js-no-trigger-title': glFeatures.issuesListDrawer,
}"
class="gl-text-primary hover:gl-text-gray-900"
data-testid="board-card-title-link"
@mousemove.stop
>{{ item.title }}</a
>

View File

@ -5,7 +5,6 @@ import produce from 'immer';
import Draggable from 'vuedraggable';
import BoardAddNewColumn from 'ee_else_ce/boards/components/board_add_new_column.vue';
import BoardAddNewColumnTrigger from '~/boards/components/board_add_new_column_trigger.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import WorkItemDrawer from '~/work_items/components/work_item_drawer.vue';
import { s__ } from '~/locale';
import { defaultSortableOptions, DRAG_DELAY } from '~/sortable/constants';
@ -39,7 +38,6 @@ export default {
GlAlert,
WorkItemDrawer,
},
mixins: [glFeatureFlagsMixin()],
inject: [
'boardType',
'canAdminList',

View File

@ -3,7 +3,6 @@ import { GlDrawer } from '@gitlab/ui';
import { DRAWER_Z_INDEX } from '~/lib/utils/constants';
import { getContentWrapperHeight } from '~/lib/utils/dom_utils';
import getMergeRequestReviewers from '~/sidebar/queries/get_merge_request_reviewers.query.graphql';
import ReviewersContainer from './reviewers_container.vue';
export default {
apollo: {
@ -23,7 +22,6 @@ export default {
},
components: {
GlDrawer,
ReviewersContainer,
ApprovalSummary: () =>
import('ee_component/merge_requests/components/reviewers/approval_summary.vue'),
ApprovalRulesWrapper: () =>
@ -65,14 +63,12 @@ export default {
<h4 class="gl-my-0">{{ __('Assign reviewers') }}</h4>
</template>
<template #header>
<approval-summary />
<approval-summary class="gl-mt-3" />
</template>
<reviewers-container
<approval-rules-wrapper
:reviewers="reviewers"
:loading-reviewers="loadingReviewers"
@request-review="(params) => $emit('request-review', params)"
@remove-reviewer="(params) => $emit('remove-reviewer', params)"
@request-review="(data) => $emit('request-review', data)"
@remove-reviewer="(data) => $emit('remove-reviewer', data)"
/>
<approval-rules-wrapper :reviewers="reviewers" />
</gl-drawer>
</template>

View File

@ -12,7 +12,6 @@ import userPermissionsQuery from './queries/user_permissions.query.graphql';
export default {
apollo: {
// eslint-disable-next-line @gitlab/vue-no-undef-apollo-properties
userPermissions: {
query: userPermissionsQuery,
variables() {
@ -50,6 +49,7 @@ export default {
searching: false,
fetchedUsers: [],
currentSelectedReviewers: this.selectedReviewers.map((r) => r.username),
userPermissions: {},
};
},
computed: {
@ -141,18 +141,16 @@ export default {
<template>
<update-reviewers
v-if="userPermissions && userPermissions.adminMergeRequest"
v-if="userPermissions.adminMergeRequest"
:selected-reviewers="currentSelectedReviewers"
>
<template #default="{ loading, updateReviewers }">
<gl-collapsible-listbox
v-model="currentSelectedReviewers"
icon="plus"
:toggle-text="$options.i18n.selectReviewer"
:toggle-text="__('Edit')"
toggle-class="!gl-text-primary"
:header-text="$options.i18n.selectReviewer"
:reset-button-label="$options.i18n.unassign"
text-sr-only
category="tertiary"
no-caret
size="small"

View File

@ -1,115 +0,0 @@
<script>
import { GlEmptyState, GlButton } from '@gitlab/ui';
import noReviewersAssignedSvg from '@gitlab/svgs/dist/illustrations/add-user-sm.svg?url';
import UncollapsedReviewerList from '~/sidebar/components/reviewers/uncollapsed_reviewer_list.vue';
import { sprintf, __, n__ } from '~/locale';
import ReviewerDropdown from '~/merge_requests/components/reviewers/reviewer_dropdown.vue';
import UpdateReviewers from './update_reviewers.vue';
import userPermissionsQuery from './queries/user_permissions.query.graphql';
export default {
apollo: {
userPermissions: {
query: userPermissionsQuery,
variables() {
return {
fullPath: this.projectPath,
iid: this.issuableIid,
};
},
update: (data) => data.project?.mergeRequest?.userPermissions || {},
},
},
components: {
GlEmptyState,
GlButton,
UncollapsedReviewerList,
UpdateReviewers,
ReviewerDropdown,
},
inject: ['projectPath', 'issuableIid'],
props: {
reviewers: {
type: Array,
required: true,
},
loadingReviewers: {
type: Boolean,
required: true,
},
},
data() {
return {
userPermissions: {},
};
},
computed: {
currentUser() {
return [gon.current_username];
},
relativeUrlRoot() {
return gon.relative_url_root ?? '';
},
reviewersTitle() {
if (this.reviewers.length === 0) {
return sprintf(__('%{count} Reviewers'), { count: this.reviewers.length });
}
return sprintf(n__('%{count} Reviewer', '%{count} Reviewers', this.reviewers.length), {
count: this.reviewers.length,
});
},
},
noReviewersAssignedSvg,
};
</script>
<template>
<div>
<div class="gl-mb-3 gl-flex gl-w-full gl-items-center gl-font-bold gl-leading-20">
<template v-if="loadingReviewers">
<div class="gl-animate-skeleton-loader gl-h-4 gl-w-20 gl-rounded-base"></div>
<div class="gl-animate-skeleton-loader gl-ml-auto gl-h-4 gl-w-4 gl-rounded-base"></div>
</template>
<template v-else>
{{ reviewersTitle }}
<reviewer-dropdown :selected-reviewers="reviewers" class="gl-ml-auto" />
</template>
</div>
<div v-if="loadingReviewers">
<div class="gl-animate-skeleton-loader gl-mb-3 gl-h-4 !gl-max-w-20 gl-rounded-base"></div>
<div class="gl-animate-skeleton-loader gl-mb-3 gl-h-4 !gl-max-w-20 gl-rounded-base"></div>
<div class="gl-animate-skeleton-loader gl-h-4 !gl-max-w-20 gl-rounded-base"></div>
</div>
<uncollapsed-reviewer-list
v-else-if="reviewers.length"
:is-editable="userPermissions.adminMergeRequest"
:root-path="relativeUrlRoot"
:users="reviewers"
issuable-type="merge_request"
@request-review="(params) => $emit('request-review', params)"
@remove-reviewer="(params) => $emit('remove-reviewer', params)"
/>
<gl-empty-state v-else :svg-path="$options.noReviewersAssignedSvg" :svg-height="70">
<template #description>
<p class="gl-mb-3 gl-font-normal">{{ __('No reviewers assigned') }}</p>
<update-reviewers
v-if="userPermissions.adminMergeRequest"
:selected-reviewers="currentUser"
>
<template #default="{ loading, updateReviewers }">
<gl-button
category="tertiary"
size="small"
:loading="loading"
data-testid="assign-yourself-button"
@click="updateReviewers"
>
{{ __('Assign yourself') }}
</gl-button>
</template>
</update-reviewers>
</template>
</gl-empty-state>
</div>
</template>

View File

@ -1,19 +1,17 @@
<script>
// NOTE! For the first iteration, we are simply copying the implementation of Assignees
// It will soon be overhauled in Issue https://gitlab.com/gitlab-org/gitlab/-/issues/233736
import { MountingPortal } from 'portal-vue';
import { GlLoadingIcon, GlButton, GlTooltipDirective } from '@gitlab/ui';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { n__, s__ } from '~/locale';
import ReviewerDrawer from '~/merge_requests/components/reviewers/reviewer_drawer.vue';
import ReviewerDropdown from '~/merge_requests/components/reviewers/reviewer_dropdown.vue';
export default {
name: 'ReviewerTitle',
components: {
MountingPortal,
GlLoadingIcon,
GlButton,
ReviewerDrawer,
ReviewerDropdown,
},
directives: {
Tooltip: GlTooltipDirective,
@ -33,11 +31,11 @@ export default {
type: Boolean,
required: true,
},
reviewers: {
type: Array,
required: false,
default: () => [],
},
data() {
return {
drawerOpen: false,
};
},
computed: {
reviewerTitle() {
@ -45,17 +43,8 @@ export default {
return n__('Reviewer', `%d Reviewers`, reviewers);
},
},
methods: {
toggleDrawerOpen(drawerOpen = !this.drawerOpen) {
if (!this.glFeatures.reviewerAssignDrawer) return;
this.drawerOpen = drawerOpen;
},
},
i18n: {
addEditReviewers: s__('MergeRequest|Add or edit reviewers'),
changeReviewer: s__('MergeRequest|Change reviewer'),
quickAdd: s__('MergeRequest|Quick add reviewers'),
},
};
</script>
@ -66,33 +55,25 @@ export default {
{{ reviewerTitle }}
<gl-loading-icon v-if="loading" size="sm" inline class="align-bottom" />
<template v-if="editable">
<reviewer-dropdown
v-if="glFeatures.reviewerAssignDrawer"
class="gl-ml-auto"
:selected-reviewers="reviewers"
/>
<gl-button
v-else
v-tooltip.hover
:title="
glFeatures.reviewerAssignDrawer
? $options.i18n.addEditReviewers
: $options.i18n.changeReviewer
"
class="hide-collapsed gl-float-right gl-ml-auto"
:class="{ 'js-sidebar-dropdown-toggle edit-link': !glFeatures.reviewerAssignDrawer }"
:title="$options.i18n.changeReviewer"
class="hide-collapsed js-sidebar-dropdown-toggle edit-link gl-float-right gl-ml-auto"
data-track-action="click_edit_button"
data-track-label="right_sidebar"
data-track-property="reviewer"
:data-testid="glFeatures.reviewerAssignDrawer ? 'drawer-toggle' : 'reviewers-edit-button'"
data-testid="reviewers-edit-button"
category="tertiary"
size="small"
@click="toggleDrawerOpen(!drawerOpen)"
>
{{ __('Edit') }}
</gl-button>
</template>
<mounting-portal v-if="glFeatures.reviewerAssignDrawer" mount-to="#js-reviewer-drawer-portal">
<reviewer-drawer
:open="drawerOpen"
@request-review="(params) => $emit('request-review', params)"
@remove-reviewer="(data) => $emit('remove-reviewer', data)"
@close="toggleDrawerOpen(false)"
/>
</mounting-portal>
</div>
</template>

View File

@ -2,11 +2,15 @@
// NOTE! For the first iteration, we are simply copying the implementation of Assignees
// It will soon be overhauled in Issue https://gitlab.com/gitlab-org/gitlab/-/issues/233736
import Vue from 'vue';
import { MountingPortal } from 'portal-vue';
import { GlButton } from '@gitlab/ui';
import { createAlert } from '~/alert';
import { TYPE_ISSUE } from '~/issues/constants';
import { __ } from '~/locale';
import { isGid, getIdFromGraphQLId } from '~/graphql_shared/utils';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { fetchUserCounts } from '~/super_sidebar/user_counts_fetch';
import ReviewerDrawer from '~/merge_requests/components/reviewers/reviewer_drawer.vue';
import eventHub from '../../event_hub';
import getMergeRequestReviewersQuery from '../../queries/get_merge_request_reviewers.query.graphql';
import mergeRequestReviewersUpdatedSubscription from '../../queries/merge_request_reviewers.subscription.graphql';
@ -18,14 +22,21 @@ export const state = Vue.observable({
issuable: {},
loading: false,
initialLoading: true,
drawerOpen: false,
});
export default {
name: 'SidebarReviewers',
components: {
MountingPortal,
GlButton,
ReviewerTitle,
Reviewers,
ReviewerDrawer,
ApprovalSummary: () =>
import('ee_component/merge_requests/components/reviewers/approval_summary.vue'),
},
mixins: [glFeatureFlagsMixin()],
props: {
mediator: {
type: Object,
@ -132,12 +143,14 @@ export default {
eventHub.$on('sidebar.addReviewer', this.addReviewer);
eventHub.$on('sidebar.removeAllReviewers', this.removeAllReviewers);
eventHub.$on('sidebar.saveReviewers', this.saveReviewers);
eventHub.$on('sidebar.toggleReviewerDrawer', this.toggleDrawerOpen);
},
beforeDestroy() {
eventHub.$off('sidebar.removeReviewer', this.removeReviewer);
eventHub.$off('sidebar.addReviewer', this.addReviewer);
eventHub.$off('sidebar.removeAllReviewers', this.removeAllReviewers);
eventHub.$off('sidebar.saveReviewers', this.saveReviewers);
eventHub.$off('sidebar.toggleReviewerDrawer', this.toggleDrawerOpen);
},
methods: {
reviewBySelf() {
@ -178,6 +191,11 @@ export default {
event.done();
}
},
toggleDrawerOpen(drawerOpen = !this.drawerOpen) {
if (!this.glFeatures.reviewerAssignDrawer) return;
this.drawerOpen = drawerOpen;
},
},
};
</script>
@ -185,12 +203,24 @@ export default {
<template>
<div>
<reviewer-title
:reviewers="reviewers"
:number-of-reviewers="reviewers.length"
:loading="isLoading"
:editable="canUpdate"
@request-review="requestReview"
@remove-reviewer="removeReviewerById"
/>
<approval-summary v-if="glFeatures.reviewerAssignDrawer" short-text class="gl-mb-2">
<gl-button
size="small"
category="tertiary"
variant="confirm"
class="gl-ml-3"
@click="toggleDrawerOpen()"
>
{{ __('Assign') }}
</gl-button>
</approval-summary>
<reviewers
v-if="!initialLoading"
:root-path="relativeUrlRoot"
@ -202,5 +232,13 @@ export default {
@assign-self="reviewBySelf"
@remove-reviewer="removeReviewerById"
/>
<mounting-portal v-if="glFeatures.reviewerAssignDrawer" mount-to="#js-reviewer-drawer-portal">
<reviewer-drawer
:open="drawerOpen"
@request-review="requestReview"
@remove-reviewer="removeReviewerById"
@close="toggleDrawerOpen(false)"
/>
</mounting-portal>
</div>
</template>

View File

@ -122,7 +122,7 @@ export default {
this.loadingStates[userId] = LOADING_STATE;
this.$emit('remove-reviewer', {
userId,
callback: () => this.requestRemovalComplete(userId),
done: () => this.requestRemovalComplete(userId),
});
},
requestReviewComplete(userId, success) {

View File

@ -1,5 +1,6 @@
#import "~/graphql_shared/fragments/user.fragment.graphql"
#import "~/graphql_shared/fragments/user_availability.fragment.graphql"
#import "ee_else_ce/sidebar/queries/reviewer_applicable_approval_rules.fragment.graphql"
query mergeRequestReviewers($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
@ -15,6 +16,8 @@ query mergeRequestReviewers($fullPath: ID!, $iid: String!) {
canUpdate
approved
reviewState
...ReviewersApplicableApprovalRules
}
}
}

View File

@ -1,5 +1,6 @@
#import "~/graphql_shared/fragments/user.fragment.graphql"
#import "~/graphql_shared/fragments/user_availability.fragment.graphql"
#import "ee_else_ce/sidebar/queries/reviewer_applicable_approval_rules.fragment.graphql"
subscription mergeRequestReviewersUpdated($issuableId: IssuableID!) {
mergeRequestReviewersUpdated(issuableId: $issuableId) {
@ -14,6 +15,8 @@ subscription mergeRequestReviewersUpdated($issuableId: IssuableID!) {
canUpdate
approved
reviewState
...ReviewersApplicableApprovalRules
}
}
}

View File

@ -0,0 +1,4 @@
fragment ReviewersApplicableApprovalRules on UserMergeRequestInteraction {
# Overriden in EE
approved
}

View File

@ -66,11 +66,17 @@ export default {
required: false,
default: false,
},
actionButtons: {
type: Array,
required: false,
default: () => [],
},
},
data() {
return {
hasApprovalAuthError: false,
isApproving: false,
userPermissions: {},
};
},
computed: {
@ -276,6 +282,7 @@ export default {
:collapsed="collapsed"
:expand-details-tooltip="__('Expand eligible approvers')"
:collapse-details-tooltip="__('Collapse eligible approvers')"
:actions="actionButtons"
@toggle="() => $emit('toggle')"
>
<template v-if="isLoading">{{ $options.FETCH_LOADING }}</template>

View File

@ -12,6 +12,8 @@ export const COMPONENTS = {
import('ee_component/vue_merge_request_widget/components/checks/locked_paths.vue'),
locked_lfs_files: () =>
import('ee_component/vue_merge_request_widget/components/checks/locked_paths.vue'),
not_approved: () =>
import('ee_component/vue_merge_request_widget/components/checks/not_approved.vue'),
};
export const FAILURE_REASONS = {

View File

@ -103,6 +103,7 @@ export default {
class="media-body gl-leading-normal"
>
<slot></slot>
</div>
<div
:class="{
'state-container-action-buttons gl-flex-wrap lg:gl-justify-end': !actions.length,
@ -114,7 +115,6 @@ export default {
<actions v-if="actions.length" :tertiary-buttons="actions" />
</slot>
</div>
</div>
<div
v-if="isCollapsible"
:class="{ 'md:gl-hidden': !collapseOnDesktop }"

View File

@ -4,7 +4,6 @@ module Import
class SourceUsersController < ApplicationController
prepend_before_action :check_feature_flag!
before_action :source_user
before_action :check_source_user_valid!
respond_to :html
@ -53,7 +52,7 @@ module Import
strong_memoize_attr :source_user
def check_feature_flag!
not_found unless Feature.enabled?(:importer_user_mapping, current_user)
not_found unless Feature.enabled?(:importer_user_mapping, source_user.reassigned_by_user)
end
def banner(partial)

View File

@ -38,6 +38,8 @@ module ViteHelper
options[:host] = URI::HTTP.build(host: ViteRuby.config.host, port: ViteRuby.config.port).to_s
end
options[:extname] = false
stylesheet_link_tag(
ViteRuby.instance.manifest.path_for("stylesheets/styles.#{path}.scss", type: :stylesheet),
**options

View File

@ -19,11 +19,6 @@ module Import
def perform(import_source_user_id, _params = {})
@import_source_user = Import::SourceUser.find_by_id(import_source_user_id)
return unless Feature.enabled?(
:importer_user_mapping,
User.actor_from_id(import_source_user&.reassigned_by_user_id)
)
return unless import_source_user_valid?
Import::ReassignPlaceholderUserRecordsService.new(import_source_user).execute

View File

@ -1,8 +1,9 @@
---
migration_job_name: BackfillApprovalGroupRulesProtectedBranchesGroupId
description: Backfills sharding key `approval_group_rules_protected_branches.group_id` from `approval_group_rules`.
description: Backfills sharding key `approval_group_rules_protected_branches.group_id`
from `approval_group_rules`.
feature_category: source_code_management
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/159584
milestone: '17.2'
queued_migration_version: 20240716135032
finalized_by: # version of the migration that finalized this BBM
finalized_by: '20240926232010'

View File

@ -0,0 +1,21 @@
# frozen_string_literal: true
class FinalizeBackfillApprovalGroupRulesProtectedBranchesGroupId < Gitlab::Database::Migration[2.2]
milestone '17.5'
disable_ddl_transaction!
restrict_gitlab_migration gitlab_schema: :gitlab_main_cell
def up
ensure_batched_background_migration_is_finished(
job_class_name: 'BackfillApprovalGroupRulesProtectedBranchesGroupId',
table_name: :approval_group_rules_protected_branches,
column_name: :id,
job_arguments: [:group_id, :approval_group_rules, :group_id, :approval_group_rule_id],
finalize: true
)
end
def down; end
end

View File

@ -0,0 +1 @@
33eb34ed1ba55339802c399e74aec4318a5e83fdbdd744e32632adbf6a452b93

View File

@ -19,8 +19,11 @@ These options are in lowercase.
### Target Types
> - Support for epics [introduced](https://gitlab.com/groups/gitlab-org/-/epics/13056) in GitLab 17.3.
Available target types for the `target_type` parameter are:
- `epic`
- `issue`
- `milestone`
- `merge_request`
@ -31,7 +34,7 @@ Available target types for the `target_type` parameter are:
- `user`
These options are in lowercase.
Events associated with epics are not available using the API.
Some epic features like child items, linked items, start dates, due dates, and health statuses are not available using the API.
Some discussions on merge requests may be of type `DiscussionNote`. These are not available using the API.
### Date formatting

View File

@ -22,7 +22,7 @@ environment, reducing the effort to assess the impact of changes. Thus, when we
and it will immediately be clear that the application can still be properly built and deployed. After all, you can _see_ it
running!
![dependencies.io](img/deployed_dependency_update.png)
![dependencies.io](img/deployed_dependency_update_v11_8.png)
However, looking at the freshly deployed code to check whether it still looks and behaves as
expected is repetitive manual work, which means it is a prime candidate for automation. This is

View File

@ -127,7 +127,7 @@ They can be added per project by navigating to the project's **Settings** > **CI
To the field **KEY**, add the name `SSH_PRIVATE_KEY`, and to the **VALUE** field, paste the private key you've copied earlier.
We'll use this variable in the `.gitlab-ci.yml` later, to easily connect to our remote server as the deployer user without entering its password.
![variables page](img/variables_page.png)
![variables page](img/variables_page_v11_6.png)
We also need to add the public key to **Project** > **Settings** > **Repository** as a [deploy key](../../../user/project/deploy_keys/index.md), which gives us the ability to access our repository from the server through the SSH protocol.
@ -140,7 +140,7 @@ cat ~/.ssh/id_rsa.pub
To the field **Title**, add any name you want, and paste the public key into the **Key** field.
![deploy keys page](img/deploy_keys_page.png)
![deploy keys page](img/deploy_keys_page_v10.png)
Now, let's clone our repository on the server just to make sure the `deployer` user has access to the repository.
@ -442,7 +442,7 @@ Now that we have our `Dockerfile` let's build and push it to our [GitLab contain
In your GitLab project repository, go to the **Registry** tab.
![container registry page empty image](img/container_registry_page_empty_image.png)
![container registry page empty image](img/container_registry_page_empty_image_v10.png)
You may need to enable the container registry for your project to see this tab. You'll find it under your project's **Settings > General > Visibility, project features, permissions**.
@ -464,7 +464,7 @@ docker push registry.gitlab.com/<USERNAME>/laravel-sample
Congratulations! You just pushed the first Docker image to the GitLab Registry, and if you refresh the page you should be able to see it:
![container registry page with image](img/container_registry_page_with_image.jpg)
![container registry page with image](img/container_registry_page_with_image_v10.jpg)
You can also [use GitLab CI/CD](https://about.gitlab.com/blog/2016/05/23/gitlab-container-registry/#use-with-gitlab-ci) to build and push your Docker images, rather than doing that on your machine.
@ -624,41 +624,41 @@ You may also want to add another job for [staging environment](https://about.git
We have prepared everything we need to test and deploy our app with GitLab CI/CD.
To do that, commit and push `.gitlab-ci.yml` to the `main` branch. It will trigger a pipeline, which you can watch live under your project's **Pipelines**.
![pipelines page](img/pipelines_page.png)
![pipelines page](img/pipelines_page_v10.png)
Here we see our **Test** and **Deploy** stages.
The **Test** stage has the `unit_test` build running.
Select it to see the runner's output.
![pipeline page](img/pipeline_page.png)
![pipeline page](img/pipeline_page_v10.png)
After our code passed through the pipeline successfully, we can deploy to our production server by selecting **Run** (**{play}**) on the right side.
![pipelines page deploy button](img/pipelines_page_deploy_button.png)
![pipelines page deploy button](img/pipelines_page_deploy_button_v10.png)
After the deploy pipeline passes successfully, go to **Pipelines > Environments**.
![environments page](img/environments_page.png)
![environments page](img/environments_page_v10.png)
If something doesn't work as expected, you can roll back to the latest working version of your app.
![environment page](img/environment_page.png)
![environment page](img/environment_page_v10.png)
By selecting the external link icon specified on the right side, GitLab opens the production website.
Our deployment successfully was done and we can see the application is live.
![Laravel welcome page](img/laravel_welcome_page.png)
![Laravel welcome page](img/laravel_welcome_page_v10.png)
In the case that you're interested to know how is the application directory structure on the production server after deployment, here are three directories named `current`, `releases` and `storage`.
As you know, the `current` directory is a symbolic link that points to the latest release.
The `.env` file consists of our Laravel environment variables.
![production server app directory](img/production_server_app_directory.png)
![production server app directory](img/production_server_app_directory_v10.png)
If you go to the `current` directory, you should see the application's content.
As you see, the `.env` is pointing to the `/var/www/app/.env` file and also `storage` is pointing to the `/var/www/app/storage/` directory.
![production server current directory](img/production_server_current_directory.png)
![production server current directory](img/production_server_current_directory_v10.png)
## Conclusion

View File

@ -52,7 +52,7 @@ To enable the plugin:
1. In your IDE, on the top bar, select your IDE's name, then select **Settings**.
1. On the left sidebar, select **Plugins**.
1. Select the **GitLab Duo** plugin, and select **Install**.
1. Select **OK**.
1. Select **OK** or **Save**.
To configure the plugin in your IDE after you enable it:
@ -65,7 +65,7 @@ To configure the plugin in your IDE after you enable it:
1. For **GitLab Personal Access Token**, paste in the personal access token you created. The token is not displayed,
nor is it accessible to others.
1. Select **Verify setup**.
1. Select **OK**.
1. Select **OK** or **Save**.
### Enable experimental or beta features
@ -110,7 +110,7 @@ To use a custom SSL certificate with GitLab Duo:
1. On the left sidebar, expand **Tools**, then select **GitLab Duo**.
1. Under **Connection**, enter the **URL to GitLab instance**.
1. To verify your connection, select **Verify setup**.
1. Select **OK**.
1. Select **OK** or **Save**.
If your IDE detects a non-trusted SSL certificate:
@ -161,18 +161,7 @@ From the IDE:
1. Select **Integrate with 1Password CLI**.
1. Optional. For **Secret reference**, paste the secret reference you copied from 1Password.
1. Optional. To verify your credentials, select **Verify setup**.
1. Select **OK**.
## Toggle sending open tabs as context
By default, the Code Suggestions use the files open in your IDE for context.
To enable or disable this feature in your IDE:
1. Go to your IDE's top menu bar and select **Settings**.
1. On the left sidebar, expand **Tools**, then select **GitLab Duo**.
1. Expand **GitLab Language Server**.
1. Under **Code Completion**, select or clear **Send open tabs as context**.
1. Select **OK**.
1. Select **OK** or **Save**.
## Report issues with the plugin
@ -195,6 +184,7 @@ built-in error reporting tool:
## Related topics
- [Code Suggestions](../../user/project/repository/code_suggestions/index.md)
- [About the Create:Editor Extensions Group](https://handbook.gitlab.com/handbook/engineering/development/dev/create/editor-extensions/)
- [Open issues for this plugin](https://gitlab.com/gitlab-org/editor-extensions/gitlab-jetbrains-plugin/-/issues/)
- [Plugin documentation](https://gitlab.com/gitlab-org/editor-extensions/gitlab-jetbrains-plugin/-/blob/main/README.md)

View File

@ -19,7 +19,7 @@ To enable debug logs in JetBrains:
1. On the top bar, go to **Help > Diagnostic Tools > Debug Log Settings**, or
search for the action by going to **Help > Find Action > Debug log settings**.
1. Add this line: `com.gitlab.plugin`
1. Select **OK**.
1. Select **OK** or **Save**.
The debug logs are available in the `idea.log` log file.
@ -66,8 +66,7 @@ To do this:
1. Confirm your default browser trusts the **URL to GitLab instance** you're using.
1. Enable the **Ignore certificate errors** option.
1. Select **Verify setup**.
1. Select **Apply**.
1. Select **OK**.
1. Select **OK** or **Save**.
## Error: `Failed to check token`
@ -79,4 +78,4 @@ GitLab Language Server process are invalid. To re-enable Code Suggestions:
1. Under **Connection**, select **Verify setup**.
1. Update your **Connection** details as needed.
1. Select **Verify setup**, and confirm that authentication succeeds.
1. Select **OK**.
1. Select **OK** or **Save**.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -114,15 +114,6 @@ This extension brings the GitLab features you use every day directly into your V
For detailed information on these features, refer to the [GitLab Workflow extension documentation](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/README.md).
## Troubleshooting
If you encounter any issues or have feature requests:
1. Check the [extension documentation](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/README.md)
for known issues and solutions.
1. Report bugs or request features in the
[`gitlab-vscode-extension` issue queue](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues).
## Related topics
- [Download the GitLab Workflow extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow)

View File

@ -0,0 +1,68 @@
---
stage: Create
group: Editor Extensions
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Using the VS Code extension with self-signed certificates
You can still use the GitLab Workflow extension for VS Code even if your GitLab instance uses a self-signed SSL certificate.
If you also use a proxy to connect to your GitLab instance, let us know in
[issue 314](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/314). If you still have connection problems
after completing these steps, review [epic 6244](https://gitlab.com/groups/gitlab-org/-/epics/6244), which links to
all existing SSL issues for the GitLab Workflow extension.
## Use the extension with a self-signed CA
Prerequisites:
- Your GitLab instance uses a certificate signed with a self-signed certificate authority (CA).
1. Ensure your CA certificate is correctly added to your system for the extension to work. VS Code reads
the system certificate store, and changes all node `http` requests to trust the certificates:
```mermaid
graph LR;
A[Self-signed CA] -- signed --> B[Your GitLab instance certificate]
```
For more information, see [Self-signed certificate error when installing Python support in WSL](https://github.com/microsoft/vscode/issues/131836#issuecomment-909983815) in the Visual Studio Code issue queue.
1. In your VS Code `settings.json`, set `"http.systemCertificates": true`. The default value is `true`, so you might not need to change this value.
1. Follow the instructions for your operating system:
### Windows
NOTE:
These instructions were tested on Windows 10 and VS Code 1.60.0.
Make sure you can see your self-signed CA in your certificate store:
1. Open the command prompt.
1. Run `certmgr`.
1. Make sure you see your certificate in **Trusted Root Certification Authorities > Certificates**.
### Linux
NOTE:
These instructions were tested on Arch Linux `5.14.3-arch1-1` and VS Code 1.60.0.
1. Use your operating system's tools to confirm you can add our self-signed CA to your system:
- `update-ca-trust` (Fedora, RHEL, CentOS)
- `update-ca-certificates` (Ubuntu, Debian, OpenSUSE, SLES)
- `trust` (Arch)
1. Confirm the CA certificate is in `/etc/ssl/certs/ca-certificates.crt` or `/etc/ssl/certs/ca-bundle.crt`.
VS Code [checks this location](https://github.com/microsoft/vscode/issues/131836#issuecomment-909983815).
### MacOS
NOTE:
These instructions are untested, but likely work as intended. If you can confirm this setup,
create a documentation issue with more information.
Make sure you see the self-signed CA in your keychain:
1. Go to **Finder > Applications > Utilities > Keychain Access**.
1. In the left-hand column, select **System**.
1. Your self-signed CA certificate should be on the list.

View File

@ -0,0 +1,123 @@
---
stage: Create
group: Editor Extensions
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Troubleshooting the GitLab Workflow extension for VS Code
If you encounter any issues with the GitLab Workflow extension for VS Code, or have feature requests for it:
1. Check the [extension documentation](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/README.md)
for known issues and solutions.
1. Report bugs or request features in the
[`gitlab-vscode-extension` issue queue](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues).
## Enable debug logs
Both the VS Code Extension and the GitLab Language Server provide logs that can help you troubleshoot. To enable debug logging:
1. In VS Code, on the top bar, go to **Code > Preferences > Settings**.
1. On the top right corner, select **Open Settings (JSON)** to edit your `settings.json` file.
1. Add this line, or edit it if it already exists:
```json
"gitlab.debug": true,
```
1. Save your changes.
### View log files
To view debug logs from either the VS Code Extension or the GitLab Language Server:
1. Use the command `GitLab: Show Extension Logs` to view the output panel.
1. In the upper right corner of the output panel, select either **GitLab Workflow** or
**GitLab Language Server** from the dropdown list.
## Error: `407 Access Denied` failure with a proxy
If you use an authenticated proxy, you might encounter an error like `407 Access Denied (authentication_failed)`:
```plaintext
Request failed: Can't add GitLab account for https://gitlab.com. Check your instance URL and network connection.
Fetching resource from https://gitlab.com/api/v4/personal_access_tokens/self failed
```
GitLab Duo Code Suggestions does not support authenticated proxies. For the proposed feature,
see [issue 1234](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/1234) in the extension's project.
## Configure self-signed certificates
To use self-signed certificates to connect to your GitLab instance, configure them using these settings.
These settings are community contributions, because the GitLab team uses a public CA. None of the fields are required.
Prerequisites:
- You're not using the [`http.proxy` setting](https://code.visualstudio.com/docs/setup/network#_legacy-proxy-server-support)
in VS Code. For more information, see [issue 314](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/314).
| Setting name | Default | Information |
| ------------ | :-----: | ----------- |
| `gitlab.ca` | null | Deprecated. See [the SSL setup guide](ssl.md) for more information on how to set up your self-signed CA. |
| `gitlab.cert`| null | Unsupported. See [epic 6244](https://gitlab.com/groups/gitlab-org/-/epics/6244). If your self-managed GitLab instance requires a custom certificate or key pair, set this option to point to your certificate file. See `gitlab.certKey`. |
| `gitlab.certKey`| null | Unsupported. See [epic 6244](https://gitlab.com/groups/gitlab-org/-/epics/6244). If your self-managed GitLab instance requires a custom certificate or key pair, set this option to point to your certificate key file. See `gitlab.cert`. |
| `gitlab.ignoreCertificateErrors` | false | Unsupported. See [epic 6244](https://gitlab.com/groups/gitlab-org/-/epics/6244). If you use a self-managed GitLab instance with no SSL certificate, or have certificate issues that prevent you from using the extension, set this option to `true` to ignore certificate errors. |
## Disable code suggestions
Code completion is enabled by default. To disable it:
1. In VS Code, on the left sidebar, select **Extensions > GitLab Workflow**.
1. Select **Manage** (**{settings}**) **> Extension Settings**.
1. In **GitLab > Duo Code Suggestions**, clear **Enable GitLab Duo Code Suggestions**.
## Disable streaming of code generation results
By default, code generation streams AI-generated code. Streaming sends generated code
to your editor incrementally, rather than waiting for the full code snippet to generate.
This allows for a more interactive and responsive experience.
If you prefer to see code generation results only when they are complete, you can turn off streaming.
Disabling streaming means that code generation requests might be perceived
as taking longer to resolve. To disable streaming:
1. In VS Code, on the top bar, go to **Code > Settings > Settings**.
1. On the top right corner, select **Open Settings (JSON)** to edit your `settings.json` file:
![The icons on the top right corner of VS Code, including 'Open Settings.'](img/open_settings_v17_5.png)
1. In your `settings.json` file, add this line, or set it to `false` it already exists:
```json
"gitlab.featureFlags.streamCodeGenerations": false,
```
1. Save your changes.
## Error: Direct connection fails
> - Direct connection [introduced](https://gitlab.com/groups/gitlab-org/-/epics/13252) in GitLab 17.2.
To reduce latency, the Workflow extension tries to send suggestion completion requests directly to GitLab Cloud Connector,
bypassing the GitLab instance. This network connection does not use the proxy and certificate settings of the VS Code extension.
If your GitLab instance doesn't support direct connections, or your network prevents the extension from connecting to
GitLab Cloud Connector, you might see these warnings in your logs:
```plaintext
Failed to fetch direct connection details from GitLab instance.
Code suggestion requests will be sent to GitLab instance.
```
This error means your instance either doesn't support direct connections, or is misconfigured.
To fix the problem, see the [troubleshooting guide for Code Suggestions](../../user/project/repository/code_suggestions/troubleshooting.md).
If you see this error, the extension can't connect to GitLab Cloud Connector, and is reverting to use your GitLab instance:
```plaintext
Direct connection for code suggestions failed.
Code suggestion requests will be sent to your GitLab instance.
```
The indirect connection through your GitLab instance is about 100 ms slower, but otherwise works the same.
This issue is often caused by network connection problems, like with your LAN firewall or proxy settings.

View File

@ -108,11 +108,9 @@ you might write something like:
AI is non-deterministic, so you may not get the same suggestion every time with the same input.
To generate quality code, write clear, descriptive, specific tasks.
### Best practice examples
For use cases and best practices, follow the [GitLab Duo examples documentation](../../../gitlab_duo_examples.md).
#### Use open tabs as context
## Open tabs as context
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/464767) in GitLab 17.2 [with a flag](../../../../administration/feature_flags.md) named `advanced_context_resolver`. Disabled by default.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/462750) in GitLab 17.2 [with a flag](../../../../administration/feature_flags.md) named `code_suggestions_context`. Disabled by default.
@ -125,49 +123,80 @@ FLAG:
The availability of this feature is controlled by a feature flag.
For more information, see the history.
For better results from GitLab Duo Code Suggestions, ensure that Open Tabs Context is enabled in your IDE settings.
This feature uses the contents of the files currently open in your IDE to get more
accurate and relevant results from Code Suggestions. Like prompt engineering, these files
To get more accurate and relevant results from Code Suggestions and code generation, you can use
the contents of the files open in tabs in your IDE. Similar to prompt engineering, these files
give GitLab Duo more information about the standards and practices in your code project.
To get the most benefit from using your open tabs as context, open the files relevant to the code
you want to create, including configuration files. When you start work in a new file,
Code Suggestions offers you suggestions in the new file.
### Enable open tabs as context
By default, Code Suggestions uses the open files in your IDE for context when making suggestions.
Prerequisites:
- Requires GitLab 17.2 and later. Earlier GitLab versions that support Code Suggestions
cannot weight the content of open tabs more heavily than other files in your project.
- Requires a [supported code language](#advanced-context-supported-languages).
- You must have GitLab 17.2 or later. Earlier GitLab versions that support Code Suggestions
cannot weigh the content of open tabs more heavily than other files in your project.
- GitLab Duo Code Suggestions must be enabled for your project.
- Use a [supported code language](#advanced-context-supported-languages):
- Code completion: All configured languages.
- Code generation: Go, Java, JavaScript, Kotlin, Python, Ruby, Rust, TypeScript (`.ts` and `.tsx` files),
Vue, and YAML.
- For Visual Studio Code, you must have GitLab Workflow extension version 4.14.2 or later.
1. Open the files you want to provide for context. Advanced Context uses the most recently
opened or changed files for context. If you dont want a file sent as additional context, close it.
1. To fine-tune your Code Generation results, add code comments to your file that explain
what you want to build. Code Generation treats your code comments like chat. Your code comments
update the `user_instruction`, and then improve the next results you receive.
To confirm that open tabs are used as context:
As you work, GitLab Duo provides Code Suggestions that use your other open files
(within [truncation limits](#truncation-of-file-content))
as extra context.
::Tabs
:::TabTitle Visual Studio Code
1. On the top bar, go to **Code > Settings > Extensions**.
1. Search for GitLab Workflow in the list, and select the gear icon.
1. Select **Extension Settings**.
1. In your **User** settings, under **GitLab Duo Code Suggestions: Open Tabs Context**,
select **Enable Open Tabs Context to improve Code Suggestions by sharing context across open tabs**.
:::TabTitle JetBrains IDEs
1. Go to your IDE's top menu bar and select **Settings**.
1. On the left sidebar, expand **Tools**, then select **GitLab Duo**.
1. Expand **GitLab Language Server**.
1. Under **Code Completion**, select **Send open tabs as context**.
1. Select **OK** or **Save**.
::EndTabs
### Use open tabs as context
Open the files you want to provide for context:
- Open tabs uses the most recently opened or changed files.
- If you do not want a file used as additional context, close that file.
When you start working in a file, GitLab Duo uses your open files
as extra context, within [truncation limits](#truncation-of-file-content).
You can adjust your code generation results by adding code comments to your file
that explain what you want to build. Code generation treats your code comments
like chat. Your code comments update the `user_instruction`, and then improve
the next results you receive.
To learn about the code that builds the prompt, see these files:
- **Code Generation**:
- **Code generation**:
[`ee/lib/api/code_suggestions.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/api/code_suggestions.rb#L76)
in the `gitlab` repository.
- **Code Completion**:
- **Code completion**:
[`ai_gateway/code_suggestions/processing/completions.py`](https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist/-/blob/fcb3f485a8f047a86a8166aad81f93b6d82106a7/ai_gateway/code_suggestions/processing/completions.py#L273)
in the `modelops` repository.
We'd love your feedback about the Advanced Context feature in
Provide feedback about this feature in
[issue 258](https://gitlab.com/gitlab-org/editor-extensions/gitlab-lsp/-/issues/258).
### Advanced Context supported languages
## Advanced Context supported languages
The Advanced Context feature supports these languages:
- Code Completion: all configured languages.
- Code Generation: Go, Java, JavaScript, Kotlin, Python, Ruby, Rust, TypeScript (`.ts` and `.tsx` files), Vue, and YAML.
- Code completion: all configured languages.
- Code generation: Go, Java, JavaScript, Kotlin, Python, Ruby, Rust, TypeScript (`.ts` and `.tsx` files), Vue, and YAML.
## Response time

View File

@ -145,57 +145,6 @@ To do this:
::EndTabs
## Use open tabs as context
> - [Introduced](https://gitlab.com/gitlab-org/editor-extensions/gitlab-lsp/-/issues/206) in GitLab 17.2.
To enhance the accuracy and relevance of GitLab Duo Code Suggestions, enable the use of
open tabs as context in your IDE settings. This feature uses the contents of files most recently
opened or changed in your IDE to provide more tailored code suggestions, within certain truncation limits.
This extra context gives you:
- More accurate and relevant code suggestions
- Better alignment with your project's standards and practices
- Improved context for new file creation
Open tabs as context supports these languages:
- Code Completion: All configured languages.
- Code Generation: Go, Java, JavaScript, Kotlin, Python, Ruby, Rust, TypeScript (`.ts` and `.tsx` files),
Vue, and YAML.
## Enable open tabs as context
Prerequisites:
- Requires GitLab 17.1 or later.
- For GitLab self-managed instances, enable the `code_suggestions_context`and the
`advanced_context_resolver` [feature flags](../../../feature_flags.md).
- GitLab Duo Code Suggestions enabled for your project
- For Visual Studio Code, requires the GitLab Workflow extension, version 4.14.2 or later.
::Tabs
:::TabTitle Visual Studio Code
1. Install the [GitLab Workflow extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow)
from the Visual Studio Marketplace.
1. Configure the extension following the
[setup instructions](https://gitlab.com/gitlab-org/gitlab-vscode-extension#extension-settings).
1. Enable the feature by toggling the `gitlab.duoCodeSuggestions.enabledSupportedLanguages` setting.
:::TabTitle JetBrains IDEs
For installation instructions for JetBrains IDEs, see the
[GitLab JetBrains Plugin documentation](https://gitlab.com/gitlab-org/editor-extensions/gitlab-jetbrains-plugin#toggle-sending-open-tabs-as-context).
::EndTabs
When you're ready to start coding:
1. Open relevant files, including configuration files, to provide better context.
1. Close any files you don't want to be used as context.
## View multiple code suggestions
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/1325) in GitLab 17.1.

View File

@ -685,14 +685,6 @@ msgid_plural "%{count} Participants"
msgstr[0] ""
msgstr[1] ""
msgid "%{count} Reviewer"
msgid_plural "%{count} Reviewers"
msgstr[0] ""
msgstr[1] ""
msgid "%{count} Reviewers"
msgstr ""
msgid "%{count} approval required from %{name}"
msgid_plural "%{count} approvals required from %{name}"
msgstr[0] ""
@ -754,9 +746,6 @@ msgstr ""
msgid "%{count} of %{total}"
msgstr ""
msgid "%{count} optional %{label}."
msgstr ""
msgid "%{count} project"
msgid_plural "%{count} projects"
msgstr[0] ""
@ -7592,9 +7581,6 @@ msgstr ""
msgid "Assign to me"
msgstr ""
msgid "Assign yourself"
msgstr ""
msgid "Assigned"
msgstr ""
@ -33890,6 +33876,9 @@ msgstr ""
msgid "MergeChecks|All threads must be resolved"
msgstr ""
msgid "MergeChecks|Assign reviewers"
msgstr ""
msgid "MergeChecks|Enable \"Pipelines must succeed\" first."
msgstr ""
@ -34052,9 +34041,6 @@ msgstr ""
msgid "MergeRequests|started a thread on commit %{linkStart}%{commitDisplay}%{linkEnd}"
msgstr ""
msgid "MergeRequest|Add or edit reviewers"
msgstr ""
msgid "MergeRequest|Awaiting review"
msgstr ""
@ -34094,9 +34080,6 @@ msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
msgid "MergeRequest|Quick add reviewers"
msgstr ""
msgid "MergeRequest|Remove reviewer"
msgstr ""
@ -36290,9 +36273,6 @@ msgstr ""
msgid "No results found."
msgstr ""
msgid "No reviewers assigned"
msgstr ""
msgid "No runner executable"
msgstr ""
@ -38094,6 +38074,9 @@ msgstr ""
msgid "Optional"
msgstr ""
msgid "Optional approvals"
msgstr ""
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@ -46165,6 +46148,11 @@ msgstr ""
msgid "Requirement|Requirements have become work items and the legacy requirement IDs are being deprecated. Update your links to reference this item's new ID %{id}. %{linkStart}Learn more%{linkEnd}."
msgstr ""
msgid "Requires %d approval"
msgid_plural "Requires %d approvals"
msgstr[0] ""
msgstr[1] ""
msgid "Requires %d approval from eligible users."
msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""

View File

@ -96,15 +96,27 @@ describe('Board card', () => {
});
describe('when GlLabel is clicked in BoardCardInner', () => {
it("doesn't call setSelectedBoardItemsMutation", () => {
it("doesn't call setSelectedBoardItemsMutation", async () => {
mountComponent();
wrapper.findComponent(GlLabel).trigger('mouseup');
await wrapper.findComponent(GlLabel).trigger('mouseup');
expect(mockSetSelectedBoardItemsResolver).toHaveBeenCalledTimes(0);
});
});
describe('when issuable title is clicked in BoardCardInner and issuesListDrawer feature is enabled', () => {
it('calls mockSetSelectedBoardItemsResolver', async () => {
mountComponent({ provide: { glFeatures: { issuesListDrawer: true } } });
await wrapper.findByTestId('board-card-title-link').trigger('click');
await waitForPromises();
expect(mockSetActiveBoardItemResolver).toHaveBeenCalledTimes(1);
});
});
it('should not highlight the card by default', () => {
mountComponent();

View File

@ -1,134 +0,0 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { GlEmptyState, 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 UpdateReviewers from '~/merge_requests/components/reviewers/update_reviewers.vue';
import ReviewersContainer from '~/merge_requests/components/reviewers/reviewers_container.vue';
import UncollapsedReviewerList from '~/sidebar/components/reviewers/uncollapsed_reviewer_list.vue';
import userPermissionsQuery from '~/merge_requests/components/reviewers/queries/user_permissions.query.graphql';
import setReviewersMutation from '~/merge_requests/components/reviewers/queries/set_reviewers.mutation.graphql';
let wrapper;
let setReviewersMutationHandler;
Vue.use(VueApollo);
function createComponent(propsData = {}, adminMergeRequest = true) {
setReviewersMutationHandler = jest.fn().mockResolvedValue({
data: { mergeRequestSetReviewers: { errors: null } },
});
const apolloProvider = createMockApollo([
[
userPermissionsQuery,
jest.fn().mockResolvedValue({
data: {
project: { id: 1, mergeRequest: { id: 1, userPermissions: { adminMergeRequest } } },
},
}),
],
[setReviewersMutation, setReviewersMutationHandler],
]);
wrapper = shallowMountExtended(ReviewersContainer, {
apolloProvider,
propsData: {
reviewers: [],
loadingReviewers: false,
...propsData,
},
provide: {
projectPath: 'gitlab-org/gitlab',
issuableIid: '1',
},
stubs: {
GlEmptyState,
UpdateReviewers,
},
});
}
const findEmptyState = () => wrapper.findComponent(GlEmptyState);
const findAssignButton = () => wrapper.findComponent(GlButton);
const findReviewersList = () => wrapper.findComponent(UncollapsedReviewerList);
const findUpdateReviewers = () => wrapper.findComponent(UpdateReviewers);
describe('Reviewers container component', () => {
beforeEach(() => {
window.gon = { current_username: 'root' };
});
afterEach(() => {
window.gon = {};
});
describe('when no reviewers exist', () => {
it('renders empty state', () => {
createComponent();
expect(findEmptyState().exists()).toBe(true);
});
describe('when user has permission to add reviewers', () => {
it('renders empty state with add reviewers button', async () => {
createComponent();
await waitForPromises();
expect(findAssignButton().exists()).toBe(true);
});
it('sets current user as update-reviewers component prop', async () => {
createComponent();
await waitForPromises();
expect(findUpdateReviewers().props('selectedReviewers')).toEqual(
expect.arrayContaining(['root']),
);
});
it('adds current user as reviewer', async () => {
createComponent();
await waitForPromises();
findAssignButton().vm.$emit('click');
await waitForPromises();
expect(setReviewersMutationHandler).toHaveBeenCalledWith(
expect.objectContaining({
reviewerUsernames: ['root'],
}),
);
});
});
describe('when user does not have permission to add reviewers', () => {
it('renders empty state with add reviewers button', async () => {
createComponent({}, false);
await waitForPromises();
expect(findAssignButton().exists()).toBe(false);
});
});
});
it('renders reviewers list component', async () => {
createComponent({ reviewers: ['test-reviewer'] });
await waitForPromises();
expect(findReviewersList().exists()).toBe(true);
expect(findReviewersList().props()).toEqual(
expect.objectContaining({
users: ['test-reviewer'],
issuableType: 'merge_request',
}),
);
});
});

View File

@ -2,9 +2,7 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { GlLoadingIcon } from '@gitlab/ui';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import { mockTracking, triggerEvent } from 'helpers/tracking_helper';
import waitForPromises from 'helpers/wait_for_promises';
import createMockApollo from 'helpers/mock_apollo_helper';
import Component from '~/sidebar/components/reviewers/reviewer_title.vue';
import getMergeRequestReviewers from '~/sidebar/queries/get_merge_request_reviewers.query.graphql';
@ -16,7 +14,6 @@ describe('ReviewerTitle component', () => {
let wrapper;
const findEditButton = () => wrapper.findByTestId('reviewers-edit-button');
const findDrawerToggle = () => wrapper.findByTestId('drawer-toggle');
const createComponent = (props, { reviewerAssignDrawer = false } = {}) => {
const apolloProvider = createMockApollo([
@ -126,44 +123,4 @@ describe('ReviewerTitle component', () => {
expect(findEditButton().attributes('title')).toBe('Change reviewer');
});
describe('when reviewerAssignDrawer is enabled', () => {
beforeEach(() => {
setHTMLFixture('<div id="js-reviewer-drawer-portal"></div>');
});
afterEach(() => {
resetHTMLFixture();
});
it('sets title for drawer toggle as `Add or edit reviewers`', async () => {
wrapper = createComponent(
{
editable: true,
},
{ reviewerAssignDrawer: true },
);
await waitForPromises();
expect(findDrawerToggle().attributes('title')).toBe('Add or edit reviewers');
});
it('clicking toggle opens reviewer drawer', async () => {
wrapper = createComponent(
{
editable: true,
},
{ reviewerAssignDrawer: true },
);
expect(document.querySelector('.gl-drawer')).toBe(null);
findDrawerToggle().vm.$emit('click');
await waitForPromises();
expect(document.querySelector('.gl-drawer')).not.toBe(null);
});
});
});

View File

@ -33,6 +33,12 @@ describe('sidebar reviewers', () => {
changing: false,
...props,
},
provide: {
projectPath: 'projectPath',
issuableId: 1,
issuableIid: 1,
multipleApprovalRulesAvailable: false,
},
// Attaching to document is required because this component emits something from the parent element :/
attachTo: document.body,
});

View File

@ -9,7 +9,7 @@ RSpec.describe Gitlab::AppTextLogger do
let(:string_message) { 'Information' }
it 'logs a hash as string' do
expect(subject.format_message('INFO', Time.now, nil, hash_message )).to include(hash_message.to_s)
expect(subject.format_message('INFO', Time.now, nil, hash_message)).to include(hash_message.to_s)
end
it 'logs a string unchanged' do

View File

@ -938,17 +938,19 @@ RSpec.describe Group, feature_category: :groups_and_projects do
group.destroy!
end
let!(:group_1) { create(:group, name: 'Y group') }
let!(:group_2) { create(:group, name: 'J group', created_at: 2.days.ago, updated_at: 1.day.ago) }
let!(:group_3) { create(:group, name: 'A group') }
let!(:group_4) { create(:group, name: 'F group', created_at: 1.day.ago, updated_at: 1.day.ago) }
let!(:group_1) { create(:group, id: 10, name: 'Y group') }
let!(:group_2) { create(:group, id: 11, name: 'J group', created_at: 2.days.ago, updated_at: 1.day.ago) }
let!(:group_3) { create(:group, id: 12, name: 'A group') }
let!(:group_4) { create(:group, id: 13, name: 'F group', created_at: 1.day.ago, updated_at: 1.day.ago) }
subject { described_class.with_statistics.with_route.sort_by_attribute(sort) }
context 'when sort by is not provided (id desc by default)' do
context 'when sort by is not provided' do
let(:sort) { nil }
it { is_expected.to eq([group_1, group_2, group_3, group_4]) }
it 'results are not ordered' do
is_expected.to contain_exactly(group_1, group_2, group_3, group_4)
end
end
context 'when sort by name_asc' do
@ -975,30 +977,18 @@ RSpec.describe Group, feature_category: :groups_and_projects do
it { is_expected.to eq([group_1, group_2, group_3, group_4].sort_by(&:path).reverse) }
end
context 'when sort by recently_created' do
context 'when sort by created_desc' do
let(:sort) { 'created_desc' }
it { is_expected.to eq([group_3, group_1, group_4, group_2]) }
end
context 'when sort by oldest_created' do
context 'when sort by created_asc' do
let(:sort) { 'created_asc' }
it { is_expected.to eq([group_2, group_4, group_1, group_3]) }
end
context 'when sort by latest_activity' do
let(:sort) { 'latest_activity_desc' }
it { is_expected.to eq([group_1, group_2, group_3, group_4]) }
end
context 'when sort by oldest_activity' do
let(:sort) { 'latest_activity_asc' }
it { is_expected.to eq([group_1, group_2, group_3, group_4]) }
end
context 'when sort by storage_size_desc' do
let!(:project_1) do
create(:project,

View File

@ -2072,7 +2072,6 @@
- './ee/spec/services/boards/lists/update_service_spec.rb'
- './ee/spec/services/boards/update_service_spec.rb'
- './ee/spec/services/boards/user_preferences/update_service_spec.rb'
- './ee/spec/services/branches/delete_service_spec.rb'
- './ee/spec/services/ci/audit_variable_change_service_spec.rb'
- './ee/spec/services/ci_cd/github_integration_setup_service_spec.rb'
- './ee/spec/services/ci_cd/github_setup_service_spec.rb'

View File

@ -51,18 +51,6 @@ RSpec.describe Import::ReassignPlaceholderUserRecordsWorker, feature_category: :
it_behaves_like 'an invalid source user'
end
context 'when the feature flag is disabled' do
before do
stub_feature_flags(importer_user_mapping: false)
end
it 'does not enqueue service to map records to real users' do
expect(Import::ReassignPlaceholderUserRecordsService).not_to receive(:new)
perform_multiple(job_args)
end
end
it 'queues a DeletePlaceholderUserWorker with the source user ID' do
expect(Import::DeletePlaceholderUserWorker)
.to receive(:perform_async).with(import_source_user.id)