Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-04-01 00:19:04 +00:00
parent 4df10dee37
commit 495c2f372a
86 changed files with 585 additions and 602 deletions

View File

@ -58,9 +58,6 @@ export default {
'app/assets/javascripts/ci/pipelines_page/components/pipelines_artifacts.vue',
'app/assets/javascripts/ci/pipelines_page/pipelines.vue',
'app/assets/javascripts/ci/reports/components/report_section.vue',
'app/assets/javascripts/clusters_list/components/agents.vue',
'app/assets/javascripts/clusters_list/components/delete_agent_button.vue',
'app/assets/javascripts/clusters_list/components/install_agent_modal.vue',
'app/assets/javascripts/commit/pipelines/legacy_pipelines_table_wrapper.vue',
'app/assets/javascripts/content_editor/components/bubble_menus/media_bubble_menu.vue',
'app/assets/javascripts/content_editor/components/content_editor.vue',
@ -76,7 +73,6 @@ export default {
'app/assets/javascripts/custom_emoji/pages/index.vue',
'app/assets/javascripts/deploy_freeze/components/deploy_freeze_modal.vue',
'app/assets/javascripts/deploy_freeze/components/deploy_freeze_table.vue',
'app/assets/javascripts/deployments/components/deployment_header.vue',
'app/assets/javascripts/design_management/components/design_description/description_form.vue',
'app/assets/javascripts/design_management/components/design_notes/design_discussion.vue',
'app/assets/javascripts/design_management/components/design_notes/design_note.vue',
@ -92,15 +88,6 @@ export default {
'app/assets/javascripts/diffs/components/diff_view.vue',
'app/assets/javascripts/diffs/components/image_diff_overlay.vue',
'app/assets/javascripts/emoji/components/picker.vue',
'app/assets/javascripts/environments/components/canary_update_modal.vue',
'app/assets/javascripts/environments/components/deployment.vue',
'app/assets/javascripts/environments/components/empty_state.vue',
'app/assets/javascripts/environments/components/enable_review_app_modal.vue',
'app/assets/javascripts/environments/components/environment_flux_resource_selector.vue',
'app/assets/javascripts/environments/components/environment_form.vue',
'app/assets/javascripts/environments/environment_details/components/deployment_actions.vue',
'app/assets/javascripts/environments/environment_details/components/deployment_history.vue',
'app/assets/javascripts/environments/environment_details/components/kubernetes/kubernetes_overview.vue',
'app/assets/javascripts/error_tracking/components/error_details.vue',
'app/assets/javascripts/error_tracking/components/error_tracking_list.vue',
'app/assets/javascripts/error_tracking_settings/components/project_dropdown.vue',
@ -144,8 +131,6 @@ export default {
'app/assets/javascripts/invite_members/components/user_limit_notification.vue',
'app/assets/javascripts/jira_connect/branches/components/new_branch_form.vue',
'app/assets/javascripts/jira_import/components/jira_import_form.vue',
'app/assets/javascripts/kubernetes_dashboard/components/workload_details.vue',
'app/assets/javascripts/kubernetes_dashboard/components/workload_details_drawer.vue',
'app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue',
'app/assets/javascripts/merge_request_dashboard/components/status_badge.vue',
'app/assets/javascripts/merge_requests/components/reviewers/reviewer_drawer.vue',
@ -448,9 +433,6 @@ export default {
'ee/app/assets/javascripts/projects/components/move_personal_project_to_group_modal.vue',
'ee/app/assets/javascripts/projects/merge_requests/blocking_mr_input_root.vue',
'ee/app/assets/javascripts/projects/settings/branch_rules/components/view/index.vue',
'ee/app/assets/javascripts/protected_environments/create_protected_environment.vue',
'ee/app/assets/javascripts/protected_environments/edit_protected_environment_rules_card.vue',
'ee/app/assets/javascripts/protected_environments/protected_environments.vue',
'ee/app/assets/javascripts/related_items_tree/components/create_epic_form.vue',
'ee/app/assets/javascripts/related_items_tree/components/related_items_tree_app.vue',
'ee/app/assets/javascripts/related_items_tree/components/related_items_tree_header_actions.vue',

View File

@ -162,3 +162,5 @@ config:
]
ignores:
- "doc/architecture"
customRules:
- "./doc/.markdownlint/rules/unnecessary_traversal.js"

View File

@ -69,11 +69,6 @@ export default {
required: true,
type: Array,
},
defaultBranchName: {
default: '.noBranch',
required: false,
type: String,
},
maxAgents: {
default: null,
required: false,
@ -423,7 +418,6 @@ export default {
v-if="action.name === 'delete-agent'"
:key="action.name"
:agent="item"
:default-branch-name="defaultBranchName"
/>
<gl-disclosure-dropdown-item
v-else

View File

@ -119,7 +119,6 @@ export default {
},
data() {
return {
folderList: {},
feedbackBannerDismissed: false,
queryErrored: false,
sharedAgentsQueryErrored: false,
@ -292,12 +291,7 @@ export default {
{{ $options.i18n.error }}
</gl-alert>
<agent-table
v-else
:agents="tab.agents"
:default-branch-name="defaultBranchName"
:max-agents="limit"
/>
<agent-table v-else :agents="tab.agents" :max-agents="limit" />
</gl-tab>
<gl-tab v-if="availableConfigs.length" :title="$options.i18n.availableConfigs">

View File

@ -36,11 +36,6 @@ export default {
type: Object,
validator: (value) => ['id', 'name'].every((prop) => value[prop]),
},
defaultBranchName: {
default: '.noBranch',
required: false,
type: String,
},
},
data() {
return {

View File

@ -194,6 +194,8 @@ export default {
}
this.registerAgent();
},
// This method is triggered from outside of the component
// eslint-disable-next-line vue/no-unused-properties
showModalForAgent(name) {
this.agentName = name;
this.$refs.modal?.show();

View File

@ -55,9 +55,6 @@ export default {
},
},
computed: {
iid() {
return this.deployment.iid;
},
status() {
return this.deployment.status?.toLowerCase() ?? '';
},

View File

@ -48,7 +48,7 @@ export default {
static: true,
},
data() {
return { error: '', dismissed: true };
return { error: '' };
},
computed: {
stableWeight() {

View File

@ -71,9 +71,6 @@ export default {
const dateTime = new Date(this.deploymentTime);
return localeDateFormat.asDateTimeFull.format(dateTime);
},
createdAt() {
return this.deployment?.createdAt;
},
commit() {
return this.deployment?.commit;
},

View File

@ -24,14 +24,6 @@ export default {
default: false,
},
},
computed: {
title() {
return this.hasTerm ? this.$options.i18n.searchingTitle : this.$options.i18n.title;
},
content() {
return this.hasTerm ? this.$options.i18n.searchingContent : this.$options.i18n.content;
},
},
i18n: {
title: s__('Environments|Get started with environments'),
content: s__(

View File

@ -47,11 +47,6 @@ export default {
- if: $CI_PIPELINE_SOURCE == "merge_request_event"`;
},
},
methods: {
commaOrPeriod(index, length) {
return index + 1 === length ? '.' : ',';
},
},
i18n,
configuringReviewAppsPath: helpPagePath('ci/review_apps/_index.md', {
anchor: 'configure-review-apps',

View File

@ -61,10 +61,7 @@ export default {
fluxKustomizations: {
query: fluxKustomizationsQuery,
variables() {
return {
configuration: this.configuration,
namespace: this.namespace,
};
return this.variables;
},
skip() {
return !this.namespace;
@ -85,10 +82,7 @@ export default {
fluxHelmReleases: {
query: fluxHelmReleasesQuery,
variables() {
return {
configuration: this.configuration,
namespace: this.namespace,
};
return this.variables;
},
skip() {
return !this.namespace;

View File

@ -103,13 +103,9 @@ export default {
selectedAgentId: this.environment.clusterAgentId,
agentSearchTerm: '',
selectedNamespace: this.environment.kubernetesNamespace,
kubernetesError: '',
};
},
computed: {
loadingNamespacesList() {
return this.$apollo.queries.k8sNamespaces.loading;
},
isNameDisabled() {
return Boolean(this.environment.id);
},

View File

@ -80,9 +80,6 @@ export default {
isActionsShown() {
return this.actions.length > 0;
},
deploymentIid() {
return this.approvalEnvironment.deploymentIid;
},
environment() {
return this.approvalEnvironment.environment;
},

View File

@ -104,9 +104,6 @@ export default {
isPaginationDisabled() {
return this.isLoading || this.isPrefetchingPages;
},
pollingInterval() {
return this.graphqlEtagKey ? ENVIRONMENT_DETAILS_QUERY_POLLING_INTERVAL : null;
},
isDirectionAscending() {
return this.sortDirection === DIRECTION_ASCENDING;
},

View File

@ -132,7 +132,6 @@ export default {
podsLoading: false,
activeTab: k8sResourceType.k8sPods,
fluxApiError: '',
focusedElement: null,
podToDelete: {},
fluxHelmRelease: {},
fluxKustomization: {},

View File

@ -179,13 +179,13 @@ export default {
</gl-badge>
</div>
</workload-details-item>
<workload-details-item v-if="item.status && !item.fullStatus" :label="$options.i18n.status">
<workload-details-item v-if="item.status && !hasFullStatus" :label="$options.i18n.status">
<gl-badge :variant="$options.WORKLOAD_STATUS_BADGE_VARIANTS[item.status]">{{
$options.STATUS_LABELS[item.status]
}}</gl-badge>
</workload-details-item>
<workload-details-item
v-if="item.fullStatus"
v-if="hasFullStatus"
:label="$options.i18n.status"
:is-expanded="expanded.status"
collapsible

View File

@ -41,6 +41,8 @@ export default {
onDeletePod(pod) {
this.$emit('delete-pod', pod);
},
// This method is triggered from outside of the component
// eslint-disable-next-line vue/no-unused-properties
toggle(item, section) {
if (!isEqual(item, this.selectedItem)) {
this.open(item, section);

View File

@ -15,11 +15,9 @@ import {
import Tracking from '~/tracking';
import {
TODO_TARGET_TYPE_ISSUE,
TODO_TARGET_TYPE_WORK_ITEM,
TODO_TARGET_TYPE_MERGE_REQUEST,
TODO_TARGET_TYPE_DESIGN,
TODO_TARGET_TYPE_ALERT,
TODO_TARGET_TYPE_EPIC,
TODO_TARGET_TYPE_SSH_KEY,
TODO_TARGET_TYPE_WIKI_PAGE,
TODO_ACTION_TYPE_ASSIGNED,
@ -65,12 +63,7 @@ export const TARGET_TYPES = [
// eslint-disable-next-line @gitlab/require-i18n-strings
id: 'Issue',
value: TODO_TARGET_TYPE_ISSUE,
title: s__('Todos|Issue'),
},
{
id: 'WorkItem',
value: TODO_TARGET_TYPE_WORK_ITEM,
title: s__('Todos|Work item'),
title: s__('Todos|Issue or Epic'),
},
{
id: 'MergeRequest',
@ -87,12 +80,6 @@ export const TARGET_TYPES = [
value: TODO_TARGET_TYPE_ALERT,
title: s__('Todos|Alert'),
},
{
// eslint-disable-next-line @gitlab/require-i18n-strings
id: 'Epic',
value: TODO_TARGET_TYPE_EPIC,
title: s__('Todos|Epic'),
},
{
// eslint-disable-next-line @gitlab/require-i18n-strings
id: 'Key',

View File

@ -4,7 +4,6 @@ export const TODO_STATE_DONE = 'done';
export const TODO_STATE_PENDING = 'pending';
export const TODO_TARGET_TYPE_ISSUE = 'ISSUE';
export const TODO_TARGET_TYPE_WORK_ITEM = 'WORKITEM';
export const TODO_TARGET_TYPE_MERGE_REQUEST = 'MERGEREQUEST';
export const TODO_TARGET_TYPE_DESIGN = 'DESIGN';
export const TODO_TARGET_TYPE_ALERT = 'ALERT';

View File

@ -91,7 +91,7 @@ export default {
v-if="isNewNote"
name="image-comment-dark"
:size="24"
class="gl-rounded-full gl-border-2 gl-border-solid gl-border-white gl-bg-white"
class="gl-rounded-full gl-border-2 gl-border-solid gl-border-neutral-0 gl-bg-neutral-0 gl-text-neutral-950"
/>
<template v-else>
{{ label }}

View File

@ -1,6 +1,5 @@
<script>
import { GlButton, GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { __ } from '~/locale';
import {
GROUP_VISIBILITY_TYPE,
PROJECT_VISIBILITY_TYPE,
@ -32,17 +31,10 @@ export default {
},
},
computed: {
isBannedProject() {
return !this.isGroup && this.visibilityLevel === 'banned';
},
visibilityIcon() {
return this.isBannedProject ? 'spam' : VISIBILITY_TYPE_ICON[this.visibilityLevel];
return VISIBILITY_TYPE_ICON[this.visibilityLevel];
},
visibilityTooltip() {
if (this.isBannedProject) {
return __('This project is hidden because its creator has been banned');
}
if (this.isGroup) {
return GROUP_VISIBILITY_TYPE[this.visibilityLevel];
}

View File

@ -28,8 +28,8 @@
.rd-hunk-header {
// this is used when a hunk header doesn't have any text, only expand buttons
min-height: calc(1em * $code-line-height);
border-top: 1px solid var(--rd-hunk-header-border-color, $gray-100);
border-bottom: 1px solid var(--rd-hunk-header-border-color, $gray-100);
border-top: 1px solid var(--rd-hunk-header-border-color, var(--gl-border-color-default));
border-bottom: 1px solid var(--rd-hunk-header-border-color, var(--gl-border-color-default));
background-color: var(--rd-hunk-header-background-color, $gray-50);
color: var(--rd-hunk-header-color, $gray-400);

View File

@ -125,8 +125,7 @@ html {
padding-left: $gl-padding;
padding-right: $gl-padding;
box-shadow: none;
background-color: $gray-10;
border-left: 1px solid $gray-100;
@apply gl-bg-subtle gl-border-l;
@include media-breakpoint-down(sm) {
min-width: unset;

View File

@ -244,7 +244,7 @@
@apply gl-transition-width;
height: $toggle-sidebar-height;
padding: 0 $gl-padding;
background-color: $gray-10;
@apply gl-bg-subtle;
border: 0;
@apply gl-text-subtle;
display: flex;
@ -252,7 +252,7 @@
@apply gl-border-b;
&:hover {
background-color: $gray-100;
@apply gl-bg-strong;
@apply gl-text-default;
}
}

View File

@ -19,21 +19,6 @@
}
}
.gl-sortable {
.header {
user-select: none;
&:hover {
cursor: pointer;
background-color: $gray-100;
}
&:focus {
outline: 1px solid $blue-300;
}
}
}
.is-dragging {
// Important because plugin sets inline CSS
opacity: 1 !important;

View File

@ -783,9 +783,7 @@ pre {
font-size: $gl-font-size;
word-break: break-all;
word-wrap: break-word;
@apply gl-text-default;
background-color: $gray-10;
border: 1px solid $gray-100;
@apply gl-text-default gl-bg-subtle gl-border;
border-radius: $border-radius-small;
// Select only code elements that will have the copy code button

View File

@ -144,7 +144,7 @@ blockquote,
color: $gl-text-color-subtle;
padding: 0 0 0 15px;
margin: 0;
border-left: 3px solid $gray-100;
border-left: 3px solid $gl-border-color-default;
}
span.highlight_word {

View File

@ -90,7 +90,7 @@ tr td {
}
tr.border-top td {
border-top: 2px solid $gray-100;
border-top: 2px solid $gl-border-color-default;
}
tr.line td {

View File

@ -34,7 +34,7 @@
.markdown-code-block pre.code {
padding: $gl-padding-8 $input-horizontal-padding;
margin: 0 0 $gl-padding-8;
border: 1px solid $gray-100;
border: 1px solid $gl-border-color-default;
border-radius: $border-radius-small;
}
}

View File

@ -103,7 +103,7 @@
.margin {
background-color: $white;
border-right: 1px solid $gray-100;
@apply gl-border-r;
.line-insert {
border-right: 1px solid $line-added-dark;

View File

@ -60,17 +60,17 @@
&,
.badge.badge-pill {
color: var(--ide-text-color, $black);
border-color: var(--ide-input-border, $gray-200);
border-color: var(--ide-input-border, var(--gl-border-color-strong));
}
}
}
.drag-handle:hover {
background-color: var(--ide-dropdown-hover-background, $gray-50);
background-color: var(--ide-dropdown-hover-background, var(--gl-background-color-strong));
}
.card-header {
background-color: var(--ide-background, $white);
background-color: var(--ide-background, var(--gl-background-color-default));
.badge.badge-pill {
background-color: var(--ide-dropdown-hover-background, $badge-bg);
@ -97,12 +97,12 @@
}
code {
background-color: var(--ide-background, $gray-100);
background-color: var(--ide-background, var(--gl-background-color-strong));
}
.ide-pipeline .top-bar,
.ide-terminal .top-bar {
background-color: var(--ide-background, $gray-10);
background-color: var(--ide-background, var(--gl-background-color-subtle));
}
.common-note-form .md-area {
@ -110,13 +110,13 @@
}
.md table:not(.code) tr th {
background-color: var(--ide-highlight-background, $gray-100);
background-color: var(--ide-highlight-background, var(--gl-background-color-strong));
}
&,
.card,
.common-note-form .md-area {
background-color: var(--ide-highlight-background, $white);
background-color: var(--ide-highlight-background, var(--gl-background-color-default));
}
.card,
@ -142,7 +142,7 @@
}
pre {
border-color: var(--ide-border-color-alt, $gray-100);
border-color: var(--ide-border-color-alt, var(--gl-border-color-default));
code {
background-color: var(--ide-empty-state-background, inherit);
@ -179,7 +179,7 @@
&,
.avatar {
color: var(--ide-text-color, var(--gl-text-color-default));
background-color: var(--ide-highlight-background, $white);
background-color: var(--ide-highlight-background, var(--gl-background-color-default));
border-color: var(--ide-highlight-background, var(--gl-avatar-border-color-default));
}
}
@ -189,7 +189,7 @@
input[type='search'],
.filtered-search-box {
border-color: var(--ide-input-border, var(--gl-border-color-default));
background: var(--ide-input-background, $white) !important;
background: var(--ide-input-background, var(--gl-background-color-default)) !important;
}
input[type='text']:not([disabled]):not([readonly]):focus,
@ -212,11 +212,11 @@
.filtered-search-token .value-container,
.filtered-search-term .value-container {
background-color: var(--ide-dropdown-hover-background, $gray-50);
background-color: var(--ide-dropdown-hover-background, var(--gl-background-color-strong));
color: var(--ide-text-color, var(--gl-text-color-default));
&:hover {
background-color: var(--ide-input-border, $gray-100);
background-color: var(--ide-input-border, var(--gl-border-color-default));
}
}
@ -245,25 +245,25 @@
}
.dropdown-menu-toggle {
border-color: var(--ide-btn-default-border, $gray-200);
border-color: var(--ide-btn-default-border, var(--gl-border-color-strong));
background-color: var(--ide-input-background, transparent);
&:hover,
&:focus {
background-color: var(--ide-dropdown-btn-hover-background, $gray-50) !important;
border-color: var(--ide-dropdown-btn-hover-border, $gray-200) !important;
background-color: var(--ide-dropdown-btn-hover-background, var(--gl-background-color-strong)) !important;
border-color: var(--ide-dropdown-btn-hover-border, var(--gl-border-color-strong)) !important;
}
}
// todo: remove this block after all default buttons have been migrated to gl-button
.btn-default:not(.gl-button) {
background-color: var(--ide-btn-default-background, $white) !important;
background-color: var(--ide-btn-default-background, var(--gl-background-color-default)) !important;
border-color: var(--ide-btn-default-border, var(--gl-border-color-default));
&:hover,
&:focus {
border-color: var(--ide-btn-default-hover-border, var(--gl-border-color-default)) !important;
background-color: var(--ide-btn-default-background, $gray-50) !important;
background-color: var(--ide-btn-default-background, var(--gl-background-color-strong)) !important;
}
&:active,
@ -276,21 +276,21 @@
.dropdown-menu {
color: var(--ide-text-color, var(--gl-text-color-default));
border-color: var(--ide-background, var(--gl-border-color-default));
background-color: var(--ide-dropdown-background, $white);
background-color: var(--ide-dropdown-background, var(--gl-background-color-default));
.nav-links {
background-color: var(--ide-dropdown-hover-background, $white);
background-color: var(--ide-dropdown-hover-background, var(--gl-background-color-default));
border-color: var(--ide-dropdown-hover-background, var(--gl-border-color-default));
}
.gl-tabs-nav {
background-color: var(--ide-dropdown-hover-background, $white);
background-color: var(--ide-dropdown-hover-background, var(--gl-background-color-default));
box-shadow: inset 0 -2px 0 0 var(--ide-dropdown-hover-background, var(--gl-border-color-default));
}
.divider {
background-color: var(--ide-dropdown-hover-background, $gray-100);
border-color: var(--ide-dropdown-hover-background, $gray-100);
background-color: var(--ide-dropdown-hover-background, var(--gl-border-color-default));
border-color: var(--ide-dropdown-hover-background, var(--gl-border-color-default));
}
li > a:not(.disable-hover):hover,
@ -298,37 +298,37 @@
li button:not(.disable-hover):hover,
li button:not(.disable-hover):focus,
li button.is-focused {
background-color: var(--ide-dropdown-hover-background, $gray-50);
background-color: var(--ide-dropdown-hover-background, var(--gl-background-color-strong));
color: var(--ide-text-color, var(--gl-text-color-default));
}
}
.dropdown-title,
.dropdown-input {
border-color: var(--ide-dropdown-hover-background, $gray-100) !important;
border-color: var(--ide-dropdown-hover-background, var(--gl-border-color-default)) !important;
}
// todo: remove this block after all disabled buttons have been migrated to gl-button
.btn[disabled]:not(.gl-button) {
background-color: var(--ide-btn-default-background, $gray-10) !important;
border: 1px solid var(--ide-btn-disabled-border, $gray-100) !important;
background-color: var(--ide-btn-default-background, var(--gl-background-color-subtle)) !important;
border: 1px solid var(--ide-btn-disabled-border, var(--gl-border-color-default)) !important;
color: var(--ide-btn-disabled-color, var(--gl-text-color-disabled)) !important;
}
.md table:not(.code) tbody {
background-color: var(--ide-empty-state-background, $white);
background-color: var(--ide-empty-state-background, var(--gl-background-color-default));
}
.animation-container {
[class^='skeleton-line-'] {
background-color: var(--ide-animation-gradient-1, $gray-100);
background-color: var(--ide-animation-gradient-1, var(--gl-border-color-default));
&::after {
background-image: linear-gradient(to right,
var(--ide-animation-gradient-1, $gray-100) 0%,
var(--ide-animation-gradient-2, $gray-10) 20%,
var(--ide-animation-gradient-1, $gray-100) 40%,
var(--ide-animation-gradient-1, $gray-100) 100%);
var(--ide-animation-gradient-1, var(--gl-border-color-default)) 0%,
var(--ide-animation-gradient-2, var(--gl-background-color-subtle)) 20%,
var(--ide-animation-gradient-1, var(--gl-border-color-default)) 40%,
var(--ide-animation-gradient-1, var(--gl-border-color-default)) 100%);
}
}
}

View File

@ -62,8 +62,8 @@ $design-pin-diameter-sm: 24px;
height: $design-pin-diameter-sm;
width: $design-pin-diameter-sm;
box-sizing: content-box;
@apply gl-bg-purple-500 dark:gl-bg-purple-700;
color: var(--white, $white);
@apply gl-text-neutral-0;
background-color: var(--gl-status-brand-icon-color);
font-weight: $gl-font-weight-bold;
border-radius: 50%;
z-index: 1;
@ -71,16 +71,16 @@ $design-pin-diameter-sm: 24px;
border: 0;
&.draft {
background-color: var(--orange-500, $orange-500);
background-color: var(--gl-status-warning-icon-color);
}
&.resolved {
background-color: var(--gray-500, $gray-500);
@apply gl-bg-strong gl-text-strong;
}
&.on-image {
box-shadow: 0 2px 4px var(--gl-color-alpha-dark-8), 0 0 1px var(--gl-color-alpha-dark-24);
border: var(--white, $white) 2px solid;
@apply gl-border-2 gl-border-solid gl-border-neutral-0;
will-change: transform, box-shadow, opacity;
// NOTE: verbose transition property required for Safari
transition: transform $general-hover-transition-duration linear, box-shadow $general-hover-transition-duration linear, opacity $general-hover-transition-duration linear;
@ -106,7 +106,7 @@ $design-pin-diameter-sm: 24px;
&.small {
position: absolute;
border: 1px solid var(--white, $white);
@apply gl-border-1 gl-border-solid gl-border-neutral-0;
height: $design-pin-diameter-sm;
width: $design-pin-diameter-sm;
}
@ -161,7 +161,7 @@ $design-pin-diameter-sm: 24px;
&::before {
content: '';
border-left: 1px solid var(--gray-100, $gray-100);
@apply gl-border-l;
position: absolute;
left: 11px;
top: -17px;

View File

@ -1,36 +1,10 @@
@import 'page_bundles/mixins_and_variables_and_functions';
.x-axis path,
.y-axis path,
.label-x-axis-line,
.label-y-axis-line {
fill: none;
stroke-width: 1;
shape-rendering: crispEdges;
}
.x-axis path,
.y-axis path {
stroke: var(--gray-300, $gray-300);
}
.label-x-axis-line,
.label-y-axis-line {
stroke: var(--gray-100, $gray-100);
}
.y-axis {
line {
stroke: var(--gray-300, $gray-300);
stroke-width: 1;
}
}
/**
* Deploy boards
*/
.deploy-board {
background-color: var(--gray-50, $gray-50);
@apply gl-bg-strong;
min-height: 20px;
> .loading-icon,

View File

@ -171,7 +171,7 @@ $ide-commit-header-height: 48px;
}
&:not([disabled]):hover {
background-color: var(--ide-input-border, $gray-100);
background-color: var(--ide-input-border, var(--gl-border-color-default));
}
&:not([disabled]):focus {

View File

@ -621,7 +621,7 @@
border: 1px solid var(--gl-border-color-default);
.circle-icon-container {
color: var(--gray-100, $gray-100);
color: var(--gl-border-color-default);
}
}
}
@ -857,8 +857,7 @@
}
.memory-graph-container {
background: var(--white, $white);
border: 1px solid var(--gray-100, $gray-100);
@apply gl-bg-default gl-border;
}
.review-bar-component {

View File

@ -24,7 +24,6 @@ $item-height: 40px;
$details-cell-width: 180px;
$timeline-cell-height: 32px;
$timeline-cell-width: 180px;
$border-style: 1px solid var(--gray-100, $gray-100);
$gradient-dark-gray: rgba(0, 0, 0, 0.15);
$gradient-gray: rgba(255, 255, 255, 0.001);
$scroll-top-gradient: linear-gradient(to bottom, $gradient-dark-gray 0%, $gradient-gray 100%);

View File

@ -21,7 +21,8 @@
// Pipeline mini graph
.pipeline-mini-graph-stage-container {
// Temoorarily sets a max height for the dropdown
position: relative;
// Temporarily sets a max height for the dropdown
// until GlDisclosureDropdown supports adding
// a max-height value
// see https://gitlab.com/gitlab-org/gitlab-ui/-/issues/3010

View File

@ -159,7 +159,7 @@ $disclosure-hierarchy-chevron-dimension: 1.2rem;
display: flex;
position: relative;
font-size: $gl-font-size-sm;
border: 1px solid var(--gray-100, $gray-100);
@apply gl-border;
border-right-style: none;
border-left-style: none;
line-height: $gl-line-height-16;
@ -177,7 +177,7 @@ $disclosure-hierarchy-chevron-dimension: 1.2rem;
width: $disclosure-hierarchy-chevron-dimension;
height: $disclosure-hierarchy-chevron-dimension;
transform: rotate(45deg) skew(14deg, 14deg);
border: 1px solid var(--gray-100, $gray-100);
@apply gl-border;
border-color: inherit;
border-bottom-color: transparent;
border-left-color: transparent;
@ -197,7 +197,7 @@ $disclosure-hierarchy-chevron-dimension: 1.2rem;
.disclosure-hierarchy-item:first-child & {
padding-left: $gl-spacing-scale-3;
border-left: 1px solid var(--gray-100, $gray-100);
@apply gl-border-l;
border-top-left-radius: $gl-border-radius-base;
border-bottom-left-radius: $gl-border-radius-base;
@ -215,7 +215,7 @@ $disclosure-hierarchy-chevron-dimension: 1.2rem;
.disclosure-hierarchy-item:last-child & {
padding-right: $gl-spacing-scale-4;
border-right: 1px solid var(--gray-100, $gray-100);
@apply gl-border-r;
border-top-right-radius: $gl-border-radius-base;
border-bottom-right-radius: $gl-border-radius-base;
@ -349,7 +349,7 @@ $disclosure-hierarchy-chevron-dimension: 1.2rem;
.work-item-design-grid {
@apply gl-grid-cols-3;
}
.work-item-design-show-sm {
@apply gl-block;
}

View File

@ -62,7 +62,7 @@
}
&:first-child {
border-top: 1px solid $gray-100;
@apply gl-border-t;
}
}

View File

@ -40,7 +40,7 @@
content: ' ';
height: 100%;
width: 4px;
background-color: $gray-100;
background-color: $gl-border-color-default;
}
position: relative;

View File

@ -59,10 +59,6 @@ class ProjectsFinder < UnionFinder
init_collection
end
if Feature.enabled?(:hide_projects_of_banned_users)
collection = without_created_and_owned_by_banned_user(collection)
end
use_cte = params.delete(:use_cte)
collection = Project.wrap_with_cte(collection) if use_cte
collection = filter_projects(collection)
@ -300,12 +296,6 @@ class ProjectsFinder < UnionFinder
{ min_access_level: params[:min_access_level] }
end
def without_created_and_owned_by_banned_user(projects)
return projects if current_user&.can?(:admin_all_resources)
projects.without_created_and_owned_by_banned_user
end
# Returns the available organizations to filter topics
def topic_organization_ids
@topic_organization_ids ||= begin

View File

@ -508,8 +508,6 @@ module ApplicationHelper
title = format(issuable_title, issuable: _('issue'))
when MergeRequest
title = format(issuable_title, issuable: _('merge request'))
when Project
title = _('This project is hidden because its creator has been banned')
end
return unless title

View File

@ -5,8 +5,6 @@ module ProjectsHelper
include CompareHelper
include Gitlab::Allowable
BANNED = 'banned'
def project_incident_management_setting
@project_incident_management_setting ||= @project.incident_management_setting ||
@project.build_incident_management_setting
@ -573,7 +571,7 @@ module ProjectsHelper
project_avatar: project.avatar_url,
project_name: project.name,
project_id: project.id,
project_visibility_level: visibility_level_name(project)
project_visibility_level: Gitlab::VisibilityLevel.string_level(project.visibility_level)
}.merge(
dropdown_attributes,
fork_button_attributes,
@ -672,10 +670,6 @@ module ProjectsHelper
end
def visibility_level_content(project, css_class: nil, icon_css_class: nil, icon_variant: nil)
if project.created_and_owned_by_banned_user? && Feature.enabled?(:hide_projects_of_banned_users)
return hidden_resource_icon(project, css_class: css_class, variant: icon_variant)
end
title = visibility_icon_description(project)
container_class = [
'has-tooltip gl-border-0 gl-bg-transparent gl-p-0 gl-leading-0 gl-text-inherit',
@ -791,14 +785,6 @@ module ProjectsHelper
}
end
def visibility_level_name(project)
if project.created_and_owned_by_banned_user? && Feature.enabled?(:hide_projects_of_banned_users)
BANNED
else
Gitlab::VisibilityLevel.string_level(project.visibility_level)
end
end
def can_admin_project_clusters?(project)
project.clusters.any? && can?(current_user, :admin_cluster, project)
end

View File

@ -1072,26 +1072,6 @@ class Project < ApplicationRecord
scope :for_group_and_its_ancestor_groups, ->(group) { where(namespace_id: group.self_and_ancestors.select(:id)) }
scope :is_importing, -> { with_import_state.where(import_state: { status: %w[started scheduled] }) }
scope :without_created_and_owned_by_banned_user, -> do
where_not_exists(
Users::BannedUser.joins(
'INNER JOIN project_authorizations ON project_authorizations.user_id = banned_users.user_id'
).where('projects.creator_id = banned_users.user_id')
.where('project_authorizations.project_id = projects.id')
.where(project_authorizations: { access_level: Gitlab::Access::OWNER })
)
end
scope :with_created_and_owned_by_banned_user, -> do
where_exists(
Users::BannedUser.joins(
'INNER JOIN project_authorizations ON project_authorizations.user_id = banned_users.user_id'
).where('projects.creator_id = banned_users.user_id')
.where('project_authorizations.project_id = projects.id')
.where(project_authorizations: { access_level: Gitlab::Access::OWNER })
)
end
class << self
# Searches for a list of projects based on the query given in `query`.
#
@ -3367,12 +3347,6 @@ class Project < ApplicationRecord
pending_delete? || hidden?
end
def created_and_owned_by_banned_user?
return false unless creator
creator.banned? && team.max_member_access(creator.id) == Gitlab::Access::OWNER
end
def work_items_feature_flag_enabled?
group&.work_items_feature_flag_enabled? || Feature.enabled?(:work_items, self)
end

View File

@ -309,10 +309,6 @@ class ProjectPolicy < BasePolicy
condition(:namespace_catalog_available) { namespace_catalog_available? }
condition(:created_and_owned_by_banned_user, scope: :subject) do
Feature.enabled?(:hide_projects_of_banned_users) && @subject.created_and_owned_by_banned_user?
end
desc "User has either planner or reporter access"
condition(:planner_or_reporter_access) do
can?(:reporter_access) || can?(:planner_access)
@ -1100,10 +1096,6 @@ class ProjectPolicy < BasePolicy
enable :write_model_experiments
end
rule { ~admin & ~organization_owner & created_and_owned_by_banned_user }.policy do
prevent :read_project
end
rule { ~private_project & guest & external_user }.enable :read_container_image
rule { can?(:create_pipeline_schedule) }.policy do

View File

@ -0,0 +1,37 @@
# frozen_string_literal: true
module Groups # rubocop:disable Gitlab/BoundedContexts -- existing top-level module
class RestoreService < Groups::BaseService
def execute
return error(_('You are not authorized to perform this action')) unless can?(current_user, :remove_group, group)
return error(_('Group has not been marked for deletion')) unless group.marked_for_deletion?
return error(_('Group deletion is in progress')) if group.deleted?
result = remove_deletion_schedule
group.reset
log_event if result[:status] == :success
result
end
private
def remove_deletion_schedule
deletion_schedule = group.deletion_schedule
if deletion_schedule.destroy
success
else
error(_('Could not restore the group'))
end
end
def log_event
log_info("User #{current_user.id} restored group #{group.full_path}")
end
end
end
Groups::RestoreService.prepend_mod

View File

@ -9,7 +9,7 @@ module Projects
end
def self.query(project_ids)
MergeRequest.opened.of_projects(project_ids)
MergeRequest.opened.without_hidden.of_projects(project_ids)
end
end
end

View File

@ -0,0 +1,61 @@
# frozen_string_literal: true
module Projects
class RestoreService < BaseService
include Gitlab::Utils::StrongMemoize
DELETED_SUFFIX_REGEX = /-deleted-[a-zA-Z0-9]+\z/
def execute
return error(_('Project already deleted')) if project.pending_delete?
result = ::Projects::UpdateService.new(
project,
current_user,
{ archived: false,
hidden: false,
marked_for_deletion_at: nil,
deleting_user: nil,
name: updated_value(project.name),
path: updated_value(project.path) }
).execute
if result[:status] == :success
log_event
## Trigger root namespace statistics refresh, to add project_statistics of
## projects restored from deletion
Namespaces::ScheduleAggregationWorker.perform_async(project.namespace_id)
end
result
end
private
def log_event
log_info("User #{current_user.id} restored project #{project.full_path}")
end
def suffix
original_path_taken?(project) ? "-#{SecureRandom.alphanumeric(5)}" : ""
end
strong_memoize_attr :suffix
def original_path_taken?(project)
existing_project = ::Project.find_by_full_path(original_value(project.full_path))
existing_project.present? && existing_project.id != project.id
end
def original_value(value)
value.sub(DELETED_SUFFIX_REGEX, '')
end
def updated_value(value)
"#{original_value(value)}#{suffix}"
end
end
end
Projects::RestoreService.prepend_mod

View File

@ -129,10 +129,7 @@
= _('access:')
%strong
= visibility_level_content(@project, css_class: visibility_level_color(@project.visibility_level))
- if @project.created_and_owned_by_banned_user? && Feature.enabled?(:hide_projects_of_banned_users)
= _('This project is hidden because its creator has been banned')
- else
= visibility_level_label(@project.visibility_level)
= visibility_level_label(@project.visibility_level)
= render 'shared/custom_attributes', custom_attributes: @project.custom_attributes

View File

@ -1,8 +0,0 @@
---
name: hide_projects_of_banned_users
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121488
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/412621
milestone: '16.2'
type: development
group: group::anti-abuse
default_enabled: false

View File

@ -1,6 +1,7 @@
- title: "GitLab.com certificate-based integration with Kubernetes"
announcement_milestone: "14.5"
removal_milestone: "15.9"
removal_milestone: "18.0"
window: 3
breaking_change: true
body: |
The certificate-based integration with Kubernetes will be [deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/). As a GitLab.com user, on new namespaces, you will no longer be able to integrate GitLab and your cluster using the certificate-based approach as of GitLab 15.0. The integration for current users will be enabled per namespace.
@ -8,9 +9,6 @@
For a more robust, secure, forthcoming, and reliable integration with Kubernetes, we recommend you use the
[agent for Kubernetes](https://docs.gitlab.com/user/clusters/agent/) to connect Kubernetes clusters with GitLab. [How do I migrate?](https://docs.gitlab.com/user/infrastructure/clusters/migrate_to_gitlab_agent/)
Although an explicit removal date is set, we don't plan to remove this feature until the new solution has feature parity.
For more information about the blockers to removal, see [this issue](https://gitlab.com/gitlab-org/configure/general/-/issues/199).
For updates and details about this deprecation, follow [this epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
GitLab Self-Managed customers can still use the feature [with a feature flag](https://docs.gitlab.com/update/deprecations/#self-managed-certificate-based-integration-with-kubernetes).

View File

@ -0,0 +1,8 @@
---
migration_job_name: BackfillAmazonInstanceAuditEventDestinations
description: Backfill the audit_events_instance_amazon_s3_configurations table to audit_events_instance_external_streaming_destinations
feature_category: audit_events
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/184039
milestone: '17.11'
queued_migration_version: 20250310151216
finalized_by: # version of the migration that finalized this BBM

View File

@ -0,0 +1,27 @@
# frozen_string_literal: true
class QueueBackfillAmazonInstanceAuditEventDestinations < Gitlab::Database::Migration[2.2]
milestone '17.11'
restrict_gitlab_migration gitlab_schema: :gitlab_main
MIGRATION = "BackfillAmazonInstanceAuditEventDestinations"
DELAY_INTERVAL = 2.minutes
BATCH_SIZE = 1000
SUB_BATCH_SIZE = 100
def up
queue_batched_background_migration(
MIGRATION,
:audit_events_instance_amazon_s3_configurations,
:id,
job_interval: DELAY_INTERVAL,
batch_size: BATCH_SIZE,
sub_batch_size: SUB_BATCH_SIZE
)
end
def down
delete_batched_background_migration(MIGRATION, :audit_events_instance_amazon_s3_configurations, :id, [])
end
end

View File

@ -0,0 +1 @@
3d5a619453f9db8266fc1a8534a64286f16037a686b9e6a54623061a20ba6e64

View File

@ -0,0 +1,53 @@
const path = require('path');
module.exports = {
names: ['Custom rule/unnecessary-traversal'],
description: 'Links should not traverse out and back into the same directory',
tags: ['gitlab-docs', 'links'],
function: (params, onError) => {
// Get the current file directory name
const { name: filePath = '', lines = [] } = params;
const dirName = path.basename(path.dirname(filePath));
if (!filePath) return;
// Process each line
lines.forEach((line, i) => {
// Skip lines that don't contain markdown links with relative paths
if (!line.includes('](../')) return;
// Regular expression to find markdown links with potential traversal issues
const linkRegex = /\[([^\]]+)\]\((\.\.\/([^/]+)\/)(.*?)(?:\s+"[^"]*")?\)/g;
let match;
while ((match = linkRegex.exec(line)) !== null) {
/*
Destructure regex match into:
- fullMatch: the entire link
- linkText: the link text
- traversalPart: the '../dir/' part
- traversalDir: just the 'dir' part
- targetPath: the rest of the path
*/
const [fullMatch, linkText, traversalPart, traversalDir, targetPath] = match;
// Check if traversal directory matches current directory
if (traversalDir === dirName) {
// Calculate positions for precise highlighting
const linkStart = match.index;
const traversalStart = fullMatch.indexOf(traversalPart);
onError({
lineNumber: i + 1,
range: [linkStart + traversalStart, traversalPart.length],
detail: `Link path does not need: '../${traversalDir}/'. Shorten link path to '[${linkText}](${targetPath})'`,
fixInfo: {
editColumn: linkStart + 1,
deleteCount: fullMatch.length,
insertText: `[${linkText}](${targetPath})`,
},
});
}
}
});
},
};

View File

@ -1,14 +1,14 @@
---
# Error: gitlab_docs.InternalLinkFormat
#
# Checks that internal link paths don't start with '/' or './'.
# Checks that internal link paths don't use `//`, or start with '/' or './'.
#
# For a list of all options, see https://vale.sh/docs/topics/styles/
extends: existence
message: "Edit the link so it does not start with '/' or './'."
message: "Edit the link so it does not use `//`, or start with '/' or './'."
link: https://docs.gitlab.com/development/documentation/styleguide/#links
vocab: false
level: error
scope: raw
raw:
- '\[[^\]]+\]\(\.?\/(?!uploads|documentation).*?\)'
- '\[[^\]]+\]\((\.?\/(?!uploads|documentation)|[^:)]*\/\/)[^)]*\)'

View File

@ -1,14 +0,0 @@
---
# Error: gitlab_docs.RelativeLinksDoubleSlashes
#
# Checks for the presence of double slashes in relative URLs.
#
# For a list of all options, see https://vale.sh/docs/topics/styles/
extends: existence
message: "Do not use double slashes '//' or '../doc' in the link path"
link: https://docs.gitlab.com/development/documentation/styleguide/#links
vocab: false
level: error
scope: raw
raw:
- '(\.//)|(\.\.\/doc\/)'

View File

@ -531,7 +531,7 @@ To set this limit to `2000` on your instance, run the following command in the G
Plan.default.actual_limits.update!(pipeline_hierarchy_size: 2000)
```
You can also set this limit by using the GitLab UI in the [Admin area](../administration/settings/continuous_integration.md#set-cicd-limits).
You can also set this limit by using the GitLab UI in the [Admin area](settings/continuous_integration.md#set-cicd-limits).
This limit is enabled on GitLab.com and cannot be changed.

View File

@ -47,7 +47,7 @@ Verify the presence of report on the base commit by obtaining the `base_sha` usi
## No Code Quality symbol in the changes view
If no symbol is displayed in the [changes view](../testing/code_quality.md#merge-request-changes-view), ensure that the `location.path` in the code quality report:
If no symbol is displayed in the [changes view](code_quality.md#merge-request-changes-view), ensure that the `location.path` in the code quality report:
- Is using a relative path to the file containing the code quality violation.
- Is not prefixed with `./`. For example, the `path` should be `somedir/file1.rb` instead of `./somedir/file1.rb`.

View File

@ -213,7 +213,7 @@ writes, but should be set to a low value, such as 10 seconds.
`Rails.cache` uses Redis as the store.
GitLab instances, like GitLab.com, can configure Redis for [key eviction](https://redis.io/docs/latest/develop/reference/eviction/).
See the [Redis development guide](../development/redis.md#caching).
See the [Redis development guide](redis.md#caching).
### When to use HTTP caching

View File

@ -69,7 +69,7 @@ enhancement. They are responsible for:
The first merge request where a feature can be tested should include the
documentation, even if the feature is behind a feature flag.
For more information, see the [guidelines](../documentation/feature_flags.md).
For more information, see the [guidelines](feature_flags.md).
The author of this MR, either a frontend or backend developer, should write the documentation.
@ -101,7 +101,7 @@ otherwise agreed with the product manager and technical writer:
If the new or changed documentation requires extensive collaboration or
conversation, a separate, linked issue can be used for the planning process.
- Use the [Documentation guidelines](../documentation/_index.md),
- Use the [Documentation guidelines](_index.md),
and other resources linked from there, including:
- [Documentation folder structure](site_architecture/folder_structure.md).
- [Documentation Style Guide](styleguide/_index.md).
@ -114,7 +114,7 @@ otherwise agreed with the product manager and technical writer:
- Want to request any other help.
- If you are working on documentation in a separate merge request, ensure the
documentation is merged as close as possible to the code merge.
- If the feature has a feature flag, [follow the policy for documenting feature-flagged issues](../documentation/feature_flags.md).
- If the feature has a feature flag, [follow the policy for documenting feature-flagged issues](feature_flags.md).
#### Review

View File

@ -118,7 +118,7 @@ Refer to [Track and Propose Sessions for Python Learning Group](https://gitlab.c
### Communication
- Stay updated by following the [learning group issue](<https://gitlab.com/gitlab-org/gitlab/-/issues/517449>)
- Stay updated by following the [learning group issue](https://gitlab.com/gitlab-org/gitlab/-/issues/517449)
- Join the discussion on Slack: **#python_getting_started**
---

View File

@ -72,6 +72,7 @@ This window takes place on May 5 - 7, 2025 from 09:00 UTC to 22:00 UTC.
| Deprecation | Impact | Stage | Scope |
|-------------|--------|-------|-------|
| [GitLab.com certificate-based integration with Kubernetes](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) | | Configure | |
| [Runner `active` GraphQL fields replaced by `paused`](https://gitlab.com/gitlab-org/gitlab/-/issues/351109) | Low | Verify | Instance, group, project |
| [ZenTao integration](https://gitlab.com/gitlab-org/gitlab/-/issues/377825) | Low | Foundations | Instance |
| [GraphQL deprecation of `dependencyProxyTotalSizeInBytes` field](https://gitlab.com/gitlab-org/gitlab/-/issues/414236) | Low | Package | Group |

View File

@ -1329,6 +1329,29 @@ You can read more about it in the [charts release page](https://docs.gitlab.com/
</div>
<div class="deprecation breaking-change" data-milestone="18.0">
### GitLab.com certificate-based integration with Kubernetes
<div class="deprecation-notes">
- Announced in GitLab <span class="milestone">14.5</span>
- Removal in GitLab <span class="milestone">18.0</span> ([breaking change](https://docs.gitlab.com/update/terminology/#breaking-change))
- To discuss this change or learn more, see the [deprecation issue](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
</div>
The certificate-based integration with Kubernetes will be [deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/). As a GitLab.com user, on new namespaces, you will no longer be able to integrate GitLab and your cluster using the certificate-based approach as of GitLab 15.0. The integration for current users will be enabled per namespace.
For a more robust, secure, forthcoming, and reliable integration with Kubernetes, we recommend you use the
[agent for Kubernetes](https://docs.gitlab.com/user/clusters/agent/) to connect Kubernetes clusters with GitLab. [How do I migrate?](https://docs.gitlab.com/user/infrastructure/clusters/migrate_to_gitlab_agent/)
For updates and details about this deprecation, follow [this epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
GitLab Self-Managed customers can still use the feature [with a feature flag](https://docs.gitlab.com/update/deprecations/#self-managed-certificate-based-integration-with-kubernetes).
</div>
<div class="deprecation " data-milestone="18.0">
### Gitaly rate limiting
@ -6331,32 +6354,6 @@ We are deprecating support for **uploading backups to remote storage** using Ope
<div class="deprecation breaking-change" data-milestone="15.9">
### GitLab.com certificate-based integration with Kubernetes
<div class="deprecation-notes">
- Announced in GitLab <span class="milestone">14.5</span>
- Removal in GitLab <span class="milestone">15.9</span> ([breaking change](https://docs.gitlab.com/update/terminology/#breaking-change))
- To discuss this change or learn more, see the [deprecation issue](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
</div>
The certificate-based integration with Kubernetes will be [deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/). As a GitLab.com user, on new namespaces, you will no longer be able to integrate GitLab and your cluster using the certificate-based approach as of GitLab 15.0. The integration for current users will be enabled per namespace.
For a more robust, secure, forthcoming, and reliable integration with Kubernetes, we recommend you use the
[agent for Kubernetes](https://docs.gitlab.com/user/clusters/agent/) to connect Kubernetes clusters with GitLab. [How do I migrate?](https://docs.gitlab.com/user/infrastructure/clusters/migrate_to_gitlab_agent/)
Although an explicit removal date is set, we don't plan to remove this feature until the new solution has feature parity.
For more information about the blockers to removal, see [this issue](https://gitlab.com/gitlab-org/configure/general/-/issues/199).
For updates and details about this deprecation, follow [this epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
GitLab Self-Managed customers can still use the feature [with a feature flag](https://docs.gitlab.com/update/deprecations/#self-managed-certificate-based-integration-with-kubernetes).
</div>
<div class="deprecation breaking-change" data-milestone="15.9">
### Live Preview no longer available in the Web IDE
<div class="deprecation-notes">

View File

@ -266,7 +266,7 @@ Prerequisites:
[enable the extension marketplace](../../administration/settings/vscode_extension_marketplace.md).
If you have the Owner role for a top-level group, you can enable the
[extension marketplace](../enterprise_user/_index.md#enable-the-extension-marketplace-for-the-web-ide-and-workspaces) for enterprise users.
[extension marketplace](_index.md#enable-the-extension-marketplace-for-the-web-ide-and-workspaces) for enterprise users.
To enable the extension marketplace for the
[Web IDE](../project/web_ide/_index.md) and [workspaces](../workspace/_index.md):

View File

@ -152,7 +152,7 @@ Alternatively, you can remove a linked item using the `/unlink` [quick action](.
## Related topics
- [Work items](../work_items/_index.md)
- [Work items](_index.md)
- [Issues](../project/issues/_index.md)
- [Epics](../group/epics/_index.md)
- [Tasks](../tasks.md)

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
module Gitlab
module BackgroundMigration
class BackfillAmazonInstanceAuditEventDestinations < BatchedMigrationJob
feature_category :audit_events
def perform
# CE implementation is a no-op
end
end
end
end
Gitlab::BackgroundMigration::BackfillAmazonInstanceAuditEventDestinations.prepend_mod

View File

@ -60792,9 +60792,6 @@ msgstr ""
msgid "This project is archived and read-only. To resume pull mirroring, unarchive the project."
msgstr ""
msgid "This project is hidden because its creator has been banned"
msgstr ""
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
@ -61643,9 +61640,6 @@ msgstr ""
msgid "Todos|Due today"
msgstr ""
msgid "Todos|Epic"
msgstr ""
msgid "Todos|Failed adding todo. Try again later."
msgstr ""
@ -61679,7 +61673,7 @@ msgstr ""
msgid "Todos|Isn't an empty To-Do List beautiful?"
msgstr ""
msgid "Todos|Issue"
msgid "Todos|Issue or Epic"
msgstr ""
msgid "Todos|It's how you always know what to work on next."
@ -61885,9 +61879,6 @@ msgstr ""
msgid "Todos|Wiki page"
msgstr ""
msgid "Todos|Work item"
msgstr ""
msgid "Todos|You"
msgstr ""

View File

@ -64,7 +64,7 @@
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/fonts": "^1.3.0",
"@gitlab/query-language-rust": "0.5.2",
"@gitlab/svgs": "3.123.0",
"@gitlab/svgs": "3.126.0",
"@gitlab/ui": "111.9.1",
"@gitlab/vue-router-vue3": "npm:vue-router@4.5.0",
"@gitlab/vuex-vue3": "npm:vuex@4.1.0",

View File

@ -25,12 +25,6 @@ RSpec.describe ProjectsFinder, feature_category: :groups_and_projects do
create(:project, :private, name: 'D', path: 'D')
end
let_it_be(:banned_user_project) do
create(:project, :public, name: 'Project created by a banned user', creator: create(:user, :banned)).tap do |p|
create(:project_authorization, :owner, user: p.creator, project: p)
end
end
let(:params) { {} }
let(:current_user) { user }
let(:project_ids_relation) { nil }
@ -554,22 +548,13 @@ RSpec.describe ProjectsFinder, feature_category: :groups_and_projects do
public_project,
internal_project,
private_project,
shared_project,
banned_user_project
shared_project
])
end
end
context 'with admin mode disabled' do
it { is_expected.to match_array([public_project, internal_project]) }
context 'when hide_projects_of_banned_users FF is disabled' do
before do
stub_feature_flags(hide_projects_of_banned_users: false)
end
it { is_expected.to match_array([public_project, internal_project, banned_user_project]) }
end
end
end
end

View File

@ -29,9 +29,6 @@ Vue.use(VueApollo);
describe('Agents', () => {
let wrapper;
const defaultProps = {
defaultBranchName: 'default',
};
const provideData = {
fullPath: 'path/to/project/group',
};
@ -94,7 +91,6 @@ describe('Agents', () => {
wrapper = shallowMount(Agents, {
apolloProvider,
propsData: {
...defaultProps,
...props,
},
provide: {

View File

@ -17,7 +17,6 @@ import { clusterAgentsResponse } from './mock_data';
Vue.use(VueApollo);
const fullPath = 'path/to/project';
const defaultBranchName = 'default';
const agent = {
id: 'agent-id',
name: 'agent-name',
@ -53,7 +52,6 @@ describe('DeleteAgentButton', () => {
query: getAgentsQuery,
variables: {
fullPath,
defaultBranchName,
isGroup: false,
},
data: clusterAgentsResponse.data,
@ -71,7 +69,6 @@ describe('DeleteAgentButton', () => {
isGroup: false,
};
const propsData = {
defaultBranchName,
agent,
};

View File

@ -19,7 +19,7 @@ exports[`Design note pin component should match the snapshot of note without ind
type="button"
>
<gl-icon-stub
class="gl-bg-white gl-border-2 gl-border-solid gl-border-white gl-rounded-full"
class="gl-bg-neutral-0 gl-border-2 gl-border-neutral-0 gl-border-solid gl-rounded-full gl-text-neutral-950"
name="image-comment-dark"
size="24"
variant="current"
@ -35,7 +35,7 @@ exports[`Design note pin component should match the snapshot when pin is resolve
type="button"
>
<gl-icon-stub
class="gl-bg-white gl-border-2 gl-border-solid gl-border-white gl-rounded-full"
class="gl-bg-neutral-0 gl-border-2 gl-border-neutral-0 gl-border-solid gl-rounded-full gl-text-neutral-950"
name="image-comment-dark"
size="24"
variant="current"
@ -50,7 +50,7 @@ exports[`Design note pin component should match the snapshot when position is ab
type="button"
>
<gl-icon-stub
class="gl-bg-white gl-border-2 gl-border-solid gl-border-white gl-rounded-full"
class="gl-bg-neutral-0 gl-border-2 gl-border-neutral-0 gl-border-solid gl-rounded-full gl-text-neutral-950"
name="image-comment-dark"
size="24"
variant="current"

View File

@ -68,11 +68,10 @@ describe('Visibility icon button', () => {
describe('if item represents project', () => {
it.each`
visibilityLevel | visibilityTooltip | visibilityIcon | tooltipPlacement
${VISIBILITY_LEVEL_PUBLIC_STRING} | ${PROJECT_VISIBILITY_TYPE[VISIBILITY_LEVEL_PUBLIC_STRING]} | ${VISIBILITY_TYPE_ICON[VISIBILITY_LEVEL_PUBLIC_STRING]} | ${'top'}
${VISIBILITY_LEVEL_INTERNAL_STRING} | ${PROJECT_VISIBILITY_TYPE[VISIBILITY_LEVEL_INTERNAL_STRING]} | ${VISIBILITY_TYPE_ICON[VISIBILITY_LEVEL_INTERNAL_STRING]} | ${'bottom'}
${VISIBILITY_LEVEL_PRIVATE_STRING} | ${PROJECT_VISIBILITY_TYPE[VISIBILITY_LEVEL_PRIVATE_STRING]} | ${VISIBILITY_TYPE_ICON[VISIBILITY_LEVEL_PRIVATE_STRING]} | ${'left'}
${'banned'} | ${'This project is hidden because its creator has been banned'} | ${'spam'} | ${'right'}
visibilityLevel | visibilityTooltip | visibilityIcon | tooltipPlacement
${VISIBILITY_LEVEL_PUBLIC_STRING} | ${PROJECT_VISIBILITY_TYPE[VISIBILITY_LEVEL_PUBLIC_STRING]} | ${VISIBILITY_TYPE_ICON[VISIBILITY_LEVEL_PUBLIC_STRING]} | ${'top'}
${VISIBILITY_LEVEL_INTERNAL_STRING} | ${PROJECT_VISIBILITY_TYPE[VISIBILITY_LEVEL_INTERNAL_STRING]} | ${VISIBILITY_TYPE_ICON[VISIBILITY_LEVEL_INTERNAL_STRING]} | ${'bottom'}
${VISIBILITY_LEVEL_PRIVATE_STRING} | ${PROJECT_VISIBILITY_TYPE[VISIBILITY_LEVEL_PRIVATE_STRING]} | ${VISIBILITY_TYPE_ICON[VISIBILITY_LEVEL_PRIVATE_STRING]} | ${'left'}
`(
'should return corresponding text when visibility level is $visibilityLevel',
({ visibilityLevel, visibilityTooltip, visibilityIcon, tooltipPlacement }) => {

View File

@ -938,13 +938,6 @@ RSpec.describe ApplicationHelper do
it_behaves_like 'returns icon with tooltip'
end
context 'when resource is a project' do
let_it_be(:resource) { build(:project) }
let(:expected_title) { 'This project is hidden because its creator has been banned' }
it_behaves_like 'returns icon with tooltip'
end
context 'when css_class is provided' do
let_it_be(:resource) { build(:issue) }

View File

@ -1294,28 +1294,6 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
end
end
describe '#visibility_level_name' do
using RSpec::Parameterized::TableSyntax
where(:banned_user, :feature_flag_enabled, :expected) do
true | true | 'banned'
false | false | 'private'
true | false | 'private'
false | true | 'private'
end
with_them do
before do
stub_feature_flags(hide_projects_of_banned_users: feature_flag_enabled)
allow(project).to receive(:created_and_owned_by_banned_user?).and_return(banned_user)
end
subject { visibility_level_name(project) }
it { is_expected.to eq(expected) }
end
end
shared_examples 'configure import method modal' do
context 'as a user' do
it 'returns a link to contact an administrator' do
@ -1835,35 +1813,6 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
end
it_behaves_like 'returns visibility level content_tag'
context 'when project creator is banned' do
let(:hidden_resource_icon) { '<svg>fake hidden resource icon</svg>' }
before do
allow(project).to receive(:created_and_owned_by_banned_user?).and_return(true)
allow(helper).to receive(:hidden_resource_icon).and_return(hidden_resource_icon)
end
it 'returns hidden resource icon' do
expect(helper.visibility_level_content(project)).to eq hidden_resource_icon
end
end
context 'with hide_projects_of_banned_users feature flag disabled' do
before do
stub_feature_flags(hide_projects_of_banned_users: false)
end
it_behaves_like 'returns visibility level content_tag'
context 'when project creator is banned' do
before do
allow(project).to receive(:created_and_owned_by_banned_user?).and_return(true)
end
it_behaves_like 'returns visibility level content_tag'
end
end
end
describe '#hidden_issue_icon' do

View File

@ -0,0 +1,38 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe QueueBackfillAmazonInstanceAuditEventDestinations,
migration: :gitlab_main,
feature_category: :audit_events do
let(:batched_migration) { described_class::MIGRATION }
it 'schedules a new batched migration' do
reversible_migration do |migration|
migration.before -> {
expect(batched_migration).not_to have_scheduled_batched_migration
}
migration.after -> {
expect(batched_migration).to have_scheduled_batched_migration(
table_name: :audit_events_instance_amazon_s3_configurations,
column_name: :id,
interval: described_class::DELAY_INTERVAL,
batch_size: described_class::BATCH_SIZE,
sub_batch_size: described_class::SUB_BATCH_SIZE,
gitlab_schema: :gitlab_main
)
}
end
end
it 'removes scheduled migration when rolling back' do
disable_migrations_output do
migrate!
schema_migrate_down!
end
expect(batched_migration).not_to have_scheduled_batched_migration
end
end

View File

@ -9529,109 +9529,6 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
end
end
describe '.without_created_and_owned_by_banned_user' do
let_it_be(:other_project) { create(:project) }
subject(:results) { described_class.without_created_and_owned_by_banned_user }
context 'when project creator is not banned' do
let_it_be(:project_of_active_user) { create(:project, creator: create(:user)) }
it 'includes the project' do
expect(results).to match_array([other_project, project_of_active_user])
end
end
context 'when project creator is banned' do
let_it_be(:banned_user) { create(:user, :banned) }
let_it_be(:project_of_banned_user) { create(:project, creator: banned_user) }
context 'when project creator is also an owner' do
let_it_be(:project_auth) do
project = project_of_banned_user
create(:project_authorization, :owner, user: project.creator, project: project)
end
it 'excludes the project' do
expect(results).to match_array([other_project])
end
end
context 'when project creator is not an owner' do
it 'includes the project' do
expect(results).to match_array([other_project, project_of_banned_user])
end
end
end
end
describe '.with_created_and_owned_by_banned_user' do
let_it_be(:other_project) { create(:project) }
subject(:results) { described_class.with_created_and_owned_by_banned_user }
context 'when project creator is not banned' do
let_it_be(:project_of_active_user) { create(:project, creator: create(:user)) }
it 'does not include the project' do
expect(results).to be_empty
end
end
context 'when project creator is banned' do
let_it_be(:banned_user) { create(:user, :banned) }
let_it_be(:project_of_banned_user) { create(:project, creator: banned_user) }
context 'when project creator is also an owner' do
let_it_be(:project_auth) do
project = project_of_banned_user
create(:project_authorization, :owner, user: project.creator, project: project)
end
it 'includes the banned user project' do
expect(results).to match_array([project_of_banned_user])
end
end
context 'when project creator is not an owner' do
it 'does not include the project' do
expect(results).not_to be_present
end
end
end
end
describe '#created_and_owned_by_banned_user?' do
subject { project.created_and_owned_by_banned_user? }
context 'when creator is banned' do
let_it_be(:creator) { create(:user, :banned) }
let_it_be(:project) { create(:project, creator: creator) }
it { is_expected.to eq false }
context 'when creator is an owner' do
let_it_be(:project_auth) do
create(:project_authorization, :owner, user: project.creator, project: project)
end
it { is_expected.to eq true }
end
end
context 'when creator is not banned' do
let_it_be(:project) { create(:project) }
it { is_expected.to eq false }
end
context 'when there is no creator' do
let_it_be(:project) { build_stubbed(:project, creator: nil) }
it { is_expected.to eq false }
end
end
it_behaves_like 'something that has web-hooks' do
let_it_be_with_reload(:object) { create(:project) }

View File

@ -124,31 +124,5 @@ RSpec.describe Namespaces::ProjectNamespacePolicy, feature_category: :groups_and
end
end
end
describe 'when project is created and owned by a banned user' do
let_it_be(:project) { create(:project, :public) }
let(:current_user) { developer }
before do
allow(project).to receive(:created_and_owned_by_banned_user?).and_return(true)
end
it { expect_disallowed(:read_project, :read_namespace) }
context 'when current user is an admin', :enable_admin_mode do
let(:current_user) { admin }
it { expect_allowed(:read_project, :read_namespace) }
end
context 'when hide_projects_of_banned_users FF is disabled' do
before do
stub_feature_flags(hide_projects_of_banned_users: false)
end
it { expect_allowed(:read_project, :read_namespace) }
end
end
end
end

View File

@ -3978,32 +3978,6 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
end
describe 'when project is created and owned by a banned user' do
let_it_be(:project) { create(:project, :public) }
let(:current_user) { guest }
before do
allow(project).to receive(:created_and_owned_by_banned_user?).and_return(true)
end
it { expect_disallowed(:read_project) }
context 'when current user is an admin', :enable_admin_mode do
let(:current_user) { admin }
it { expect_allowed(:read_project) }
end
context 'when hide_projects_of_banned_users FF is disabled' do
before do
stub_feature_flags(hide_projects_of_banned_users: false)
end
it { expect_allowed(:read_project) }
end
end
describe 'webhooks' do
context 'when the current_user is a maintainer' do
let(:current_user) { maintainer }

View File

@ -218,11 +218,10 @@ RSpec.describe 'getting project information', feature_category: :groups_and_proj
end
context 'for N+1 queries with isCatalogResource' do
let_it_be(:project1) { create(:project, group: group) }
let_it_be(:project2) { create(:project, group: group) }
let_it_be(:project1) { create(:project, group: group, owners: current_user) }
let_it_be(:project2) { create(:project, group: group, owners: current_user) }
it 'avoids N+1 database queries' do
pending('See: https://gitlab.com/gitlab-org/gitlab/-/issues/403634')
it 'avoids N+1 database queries', :request_store do
ctx = { current_user: current_user }
baseline_query = graphql_query_for(:project, { full_path: project1.full_path }, 'isCatalogResource')

View File

@ -0,0 +1,94 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Groups::RestoreService, feature_category: :groups_and_projects do
let(:user) { create(:user) }
let(:group) do
create(:group_with_deletion_schedule,
marked_for_deletion_on: 1.day.ago,
deleting_user: user)
end
subject(:execute) { described_class.new(group, user, {}).execute }
context 'when restoring the group' do
context 'with a user that can admin the group' do
before do
group.add_owner(user)
end
context 'for a group that has been marked for deletion' do
it 'removes the mark for deletion' do
execute
expect(group.marked_for_deletion_on).to be_nil
expect(group.deleting_user).to be_nil
end
it 'returns success' do
result = execute
expect(result).to eq({ status: :success })
end
context 'when restoring fails' do
it 'returns error' do
allow(group.deletion_schedule).to receive(:destroy).and_return(false)
result = execute
expect(result).to eq({ status: :error, message: 'Could not restore the group' })
end
end
end
context 'for a group that has not been marked for deletion' do
let(:group) { create(:group) }
it 'does not change the attributes associated with delayed deletion' do
execute
expect(group.marked_for_deletion_on).to be_nil
expect(group.deleting_user).to be_nil
end
it 'returns error' do
result = execute
expect(result).to eq({ status: :error, message: 'Group has not been marked for deletion' })
end
end
it 'logs the restore' do
allow(Gitlab::AppLogger).to receive(:info)
expect(::Gitlab::AppLogger).to receive(:info).with("User #{user.id} restored group #{group.full_path}")
execute
end
context 'when the group is deletion is in progress' do
before do
group.namespace_details.update!(deleted_at: Time.current)
end
it { is_expected.to eq({ status: :error, message: 'Group deletion is in progress' }) }
end
end
context 'with a user that cannot admin the group' do
it 'does not restore the group' do
execute
expect(group.marked_for_deletion?).to be_truthy
end
it 'returns error' do
result = execute
expect(result).to eq({ status: :error, message: 'You are not authorized to perform this action' })
end
end
end
end

View File

@ -15,5 +15,19 @@ RSpec.describe Projects::OpenMergeRequestsCountService, :use_clean_rails_memory_
expect(subject.count).to eq(1)
end
context 'when there are hidden merge requests' do
let(:banned_user) { create(:user, :banned) }
before do
create(:merge_request, :opened, source_project: project, target_project: project, source_branch: 'user-branch')
create(:merge_request, :opened, source_project: project, target_project: project,
source_branch: 'banned-user-branch', author: banned_user)
end
it 'does not include hidden merge requests in the count' do
expect(described_class.new(project).count).to eq(1)
end
end
end
end

View File

@ -0,0 +1,102 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Projects::RestoreService, feature_category: :groups_and_projects do
let(:user) { create(:user, :with_namespace) }
let(:pending_delete) { nil }
let(:project) do
create(:project,
:repository,
path: 'project-1-deleted-177483',
name: 'Project1 Name-deleted-177483',
namespace: user.namespace,
marked_for_deletion_at: 1.day.ago,
deleting_user: user,
archived: true,
hidden: true,
pending_delete: pending_delete)
end
context 'when restoring project' do
subject(:execute) { described_class.new(project, user).execute }
it 'marks project as not hidden, unarchived and not marked for deletion' do
expect(Namespaces::ScheduleAggregationWorker).to receive(:perform_async)
.with(project.namespace.id).and_call_original
execute
expect(Project.unscoped.all).to include(project)
expect(project.archived).to be(false)
expect(project.hidden).to be(false)
expect(project.marked_for_deletion_at).to be_nil
expect(project.deleting_user).to be_nil
end
context 'when the original project path is not taken' do
it 'renames the project back to its original path' do
expect { execute }.to change { project.path }.from("project-1-deleted-177483").to("project-1")
end
it 'renames the project back to its original name' do
expect { execute }.to change { project.name }.from("Project1 Name-deleted-177483").to("Project1 Name")
end
end
context 'when the original project name has been taken' do
before do
create(:project, path: 'project-1', name: 'Project1 Name', namespace: user.namespace, deleting_user: user)
end
it 'renames the project back to its original path with a suffix' do
expect { execute }.to change { project.path }.from("project-1-deleted-177483").to(/project-1-[a-zA-Z0-9]{5}/)
end
it 'renames the project back to its original name with a suffix' do
expect { execute }.to change { project.name }.from("Project1 Name-deleted-177483")
.to(/Project1 Name-[a-zA-Z0-9]{5}/)
end
it 'uses the same suffix for both the path and name' do
execute
path_suffix = project.path.split('-')[-1]
name_suffix = project.name.split('-')[-1]
expect(path_suffix).to eq(name_suffix)
end
end
context 'when the original project path does not contain the -deleted- suffix' do
let(:project) do
create(
:project,
:repository,
namespace: user.namespace,
marked_for_deletion_at: 1.day.ago,
deleting_user: user,
archived: true,
pending_delete: pending_delete
)
end
it 'renames the project back to its original path' do
expect { execute }.not_to change { project.path }
end
it 'renames the project back to its original name' do
expect { execute }.not_to change { project.name }
end
end
end
context 'when restoring project already in process of removal' do
let(:deletion_date) { 2.days.ago }
let(:pending_delete) { true }
it 'does not allow to restore' do
expect(described_class.new(project, user).execute).to include(status: :error)
end
end
end

View File

@ -1436,10 +1436,10 @@
stylelint-declaration-strict-value "1.10.4"
stylelint-scss "6.0.0"
"@gitlab/svgs@3.123.0":
version "3.123.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.123.0.tgz#1fa3b1a709755ff7c8ef67e18c0442101655ebf0"
integrity sha512-yjVn+utOTIKk8d9JlvGo6EgJ4TQ+CKpe3RddflAqtsQqQuL/2MlVdtaUePybxYzWIaumFuh5LouQ6BrWyw1niQ==
"@gitlab/svgs@3.126.0":
version "3.126.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.126.0.tgz#1c0bb95c11de808b78afd05dc95aca258c3b39f0"
integrity sha512-7X8uzitNn7NDcVy+FVCw8npMNEUpLGHTO5Z+BJZqVILj/FD+0WveYdPxAEVa9hXYQn5qXWM0ZAknzB9LM6Id8w==
"@gitlab/ui@111.9.1":
version "111.9.1"