Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-03-28 18:07:20 +00:00
parent e32b42405d
commit f670eb5f8c
73 changed files with 1194 additions and 438 deletions

View File

@ -238,7 +238,7 @@
{"name":"gitlab-markup","version":"2.0.0","platform":"ruby","checksum":"951a1c871463a8f329e6c002b2da337cd547febcc1e33d84df4a212419fba02e"},
{"name":"gitlab-net-dns","version":"0.10.0","platform":"ruby","checksum":"73b4613d8c851480b7b4e631f117bce4bbb4b6b8073ecf4eb167407e46097c6e"},
{"name":"gitlab-sdk","version":"0.3.1","platform":"ruby","checksum":"48ba49084f4ab92df7c7ef9f347020d9dfdf6ed9c1e782b67264e98ffe6ea710"},
{"name":"gitlab-secret_detection","version":"0.19.0","platform":"ruby","checksum":"995d87ef652dec742de8af5015018f975a01c8961a7c71892e9be19417215613"},
{"name":"gitlab-secret_detection","version":"0.21.0","platform":"ruby","checksum":"cfef3689a9706f5a507981d2159f4f8170a41c027eaf8a06551cce763ba07442"},
{"name":"gitlab-security_report_schemas","version":"0.1.2.min15.0.0.max15.2.1","platform":"ruby","checksum":"300037487ec9d51a814f648514ff521cb82b94fc51d9fe53389175b36ac680ae"},
{"name":"gitlab-styles","version":"13.1.0","platform":"ruby","checksum":"46c7c5729616355868b7b40a4ffcd052b36346076042abe8cafaee1688cbf2c1"},
{"name":"gitlab_chronic_duration","version":"0.12.0","platform":"ruby","checksum":"0d766944d415b5c831f176871ee8625783fc0c5bfbef2d79a3a616f207ffc16d"},

View File

@ -786,12 +786,14 @@ GEM
activesupport (>= 5.2.0)
rake (~> 13.0)
snowplow-tracker (~> 0.8.0)
gitlab-secret_detection (0.19.0)
gitlab-secret_detection (0.21.0)
grpc (~> 1.63)
grpc-tools (~> 1.63)
grpc_reflection (~> 0.1)
parallel (~> 1)
re2 (~> 2.7)
sentry-ruby (~> 5.22)
stackprof (~> 0.2.27)
toml-rb (~> 2.2)
gitlab-security_report_schemas (0.1.2.min15.0.0.max15.2.1)
activesupport (>= 6, < 8)

View File

@ -238,7 +238,7 @@
{"name":"gitlab-markup","version":"2.0.0","platform":"ruby","checksum":"951a1c871463a8f329e6c002b2da337cd547febcc1e33d84df4a212419fba02e"},
{"name":"gitlab-net-dns","version":"0.10.0","platform":"ruby","checksum":"73b4613d8c851480b7b4e631f117bce4bbb4b6b8073ecf4eb167407e46097c6e"},
{"name":"gitlab-sdk","version":"0.3.1","platform":"ruby","checksum":"48ba49084f4ab92df7c7ef9f347020d9dfdf6ed9c1e782b67264e98ffe6ea710"},
{"name":"gitlab-secret_detection","version":"0.19.0","platform":"ruby","checksum":"995d87ef652dec742de8af5015018f975a01c8961a7c71892e9be19417215613"},
{"name":"gitlab-secret_detection","version":"0.21.0","platform":"ruby","checksum":"cfef3689a9706f5a507981d2159f4f8170a41c027eaf8a06551cce763ba07442"},
{"name":"gitlab-security_report_schemas","version":"0.1.2.min15.0.0.max15.2.1","platform":"ruby","checksum":"300037487ec9d51a814f648514ff521cb82b94fc51d9fe53389175b36ac680ae"},
{"name":"gitlab-styles","version":"13.1.0","platform":"ruby","checksum":"46c7c5729616355868b7b40a4ffcd052b36346076042abe8cafaee1688cbf2c1"},
{"name":"gitlab_chronic_duration","version":"0.12.0","platform":"ruby","checksum":"0d766944d415b5c831f176871ee8625783fc0c5bfbef2d79a3a616f207ffc16d"},

View File

@ -798,12 +798,14 @@ GEM
activesupport (>= 5.2.0)
rake (~> 13.0)
snowplow-tracker (~> 0.8.0)
gitlab-secret_detection (0.19.0)
gitlab-secret_detection (0.21.0)
grpc (~> 1.63)
grpc-tools (~> 1.63)
grpc_reflection (~> 0.1)
parallel (~> 1)
re2 (~> 2.7)
sentry-ruby (~> 5.22)
stackprof (~> 0.2.27)
toml-rb (~> 2.2)
gitlab-security_report_schemas (0.1.2.min15.0.0.max15.2.1)
activesupport (>= 6, < 8)

View File

@ -37,6 +37,9 @@ export default {
status() {
return this.job.detailedStatus || this.job.status;
},
isFailed() {
return this.status?.group === 'failed';
},
tooltipText() {
const statusTooltip = capitalizeFirstCharacter(this.status?.tooltip);
@ -49,7 +52,12 @@ export default {
};
</script>
<template>
<gl-disclosure-dropdown-item :item="item" class="ci-job-component" data-testid="ci-job-item">
<gl-disclosure-dropdown-item
:item="item"
class="ci-job-component"
:class="{ 'ci-job-item-failed': isFailed }"
data-testid="ci-job-item"
>
<template #list-item>
<div class="-gl-my-2 gl-flex gl-items-center gl-justify-between">
<job-name-component

View File

@ -72,6 +72,9 @@ export default {
// https://gitlab.com/gitlab-org/gitlab-ui/-/issues/2615
return this.isMobile ? 'bottom-start' : 'right-start';
},
isFailed() {
return this.group?.status?.group === 'failed';
},
},
methods: {
handleResize() {
@ -100,7 +103,11 @@ export default {
@hidden="hideDropdown"
>
<template #toggle>
<button type="button" :class="cssClassJobName" class="gl-w-full gl-bg-transparent gl-pr-4">
<button
type="button"
:class="[cssClassJobName, { 'ci-job-item-failed': isFailed }]"
class="gl-w-full gl-bg-transparent gl-pr-4"
>
<div class="gl-flex gl-items-stretch gl-justify-between">
<job-item
:type="$options.jobItemTypes.jobDropdown"

View File

@ -0,0 +1,17 @@
import Vue from 'vue';
import DockerHubRateLimitsAlert from '~/vue_shared/components/docker_hub_rate_limits_alert.vue';
export default (selector = '#js-docker-hub-rate-limits-alert') => {
const containerEl = document.querySelector(selector);
if (!containerEl) {
return false;
}
return new Vue({
el: containerEl,
render(createElement) {
return createElement(DockerHubRateLimitsAlert);
},
});
};

View File

@ -1,8 +1,5 @@
import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils';
import Sidebar from '~/right_sidebar';
import { getSidebarOptions } from '~/sidebar/mount_sidebar';
import CsvImportExportButtons from './components/csv_import_export_buttons.vue';
import issuableBulkUpdateActions from './issuable_bulk_update_actions';
import IssuableBulkUpdateSidebar from './issuable_bulk_update_sidebar';
import IssuableContext from './issuable_context';
@ -18,49 +15,6 @@ export function initBulkUpdateSidebar(prefixId) {
new IssuableBulkUpdateSidebar(); // eslint-disable-line no-new
}
export function initCsvImportExportButtons() {
const el = document.querySelector('.js-csv-import-export-buttons');
if (!el) {
return null;
}
const {
showExportButton,
showImportButton,
issuableType,
issuableCount,
email,
exportCsvPath,
importCsvIssuesPath,
canEdit,
projectImportJiraPath,
maxAttachmentSize,
} = el.dataset;
return new Vue({
el,
name: 'CsvImportExportButtonsRoot',
provide: {
showExportButton: parseBoolean(showExportButton),
showImportButton: parseBoolean(showImportButton),
issuableType,
email,
importCsvIssuesPath,
canEdit: parseBoolean(canEdit),
projectImportJiraPath,
maxAttachmentSize,
},
render: (createElement) =>
createElement(CsvImportExportButtons, {
props: {
exportCsvPath,
issuableCount: parseInt(issuableCount, 10),
},
}),
});
}
export function initIssuableSidebar() {
const el = document.querySelector('.js-sidebar-options');

View File

@ -17,6 +17,7 @@ import Tracking from '~/tracking';
import PersistedPagination from '~/packages_and_registries/shared/components/persisted_pagination.vue';
import PersistedSearch from '~/packages_and_registries/shared/components/persisted_search.vue';
import MetadataDatabaseAlert from '~/packages_and_registries/shared/components/container_registry_metadata_database_alert.vue';
import DockerHubRateLimitsAlert from '~/vue_shared/components/docker_hub_rate_limits_alert.vue';
import { FILTERED_SEARCH_TERM } from '~/vue_shared/components/filtered_search_bar/constants';
import {
getPageParams,
@ -64,6 +65,7 @@ export default {
/* webpackChunkName: 'container_registry_components' */ '~/packages_and_registries/shared/components/cli_commands.vue'
),
DeleteModal,
DockerHubRateLimitsAlert,
GlSprintf,
GlLink,
GlAlert,
@ -252,6 +254,8 @@ export default {
<template>
<div>
<docker-hub-rate-limits-alert class="gl-my-5" />
<metadata-database-alert v-if="!config.isMetadataDatabaseEnabled" />
<gl-alert
v-if="showDeleteAlert"

View File

@ -7,6 +7,7 @@ import {
UPDATE_SETTINGS_SUCCESS_MESSAGE,
} from '~/packages_and_registries/settings/project/constants';
import MetadataDatabaseAlert from '~/packages_and_registries/shared/components/container_registry_metadata_database_alert.vue';
import DockerHubRateLimitsAlert from '~/vue_shared/components/docker_hub_rate_limits_alert.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import PackageRegistrySection from '~/packages_and_registries/settings/project/components/package_registry_section.vue';
import ContainerRegistrySection from '~/packages_and_registries/settings/project/components/container_registry_section.vue';
@ -14,6 +15,7 @@ import ContainerRegistrySection from '~/packages_and_registries/settings/project
export default {
components: {
ContainerRegistrySection,
DockerHubRateLimitsAlert,
GlAlert,
MetadataDatabaseAlert,
PackageRegistrySection,
@ -61,10 +63,12 @@ export default {
variant="success"
class="gl-mt-5"
dismissible
data-testid="registry-update-settings-alert"
@dismiss="showAlert = false"
>
{{ $options.i18n.UPDATE_SETTINGS_SUCCESS_MESSAGE }}
</gl-alert>
<docker-hub-rate-limits-alert class="gl-my-5" />
<metadata-database-alert v-if="!isContainerRegistryMetadataDatabaseEnabled" class="gl-mt-5" />
<package-registry-section v-if="showPackageRegistrySettings" />
<container-registry-section

View File

@ -12,6 +12,7 @@ import { initCiSecureFiles } from '~/ci_secure_files';
import initDeployTokens from '~/deploy_tokens';
import { initProjectRunnersRegistrationDropdown } from '~/ci/runner/project_runners/register';
import { initGeneralPipelinesOptions } from '~/ci_settings_general_pipeline';
import initDockerHubRateLimitsAlert from '~/docker_hub_rate_limits';
import { renderGFM } from '~/behaviors/markdown/render_gfm';
// Initialize expandable settings panels
@ -43,5 +44,6 @@ initRefSwitcherBadges();
initTokenAccess();
initCiSecureFiles();
initGeneralPipelinesOptions();
initDockerHubRateLimitsAlert();
renderGFM(document.getElementById('js-shared-runners-markdown'));

View File

@ -4,7 +4,6 @@ import { sprintf, __ } from '~/locale';
import { showForkSuggestion } from '~/repository/utils/fork_suggestion_utils';
import { DEFAULT_BLOB_INFO } from '~/repository/constants';
import getRefMixin from '~/repository/mixins/get_ref';
import ForkSuggestionModal from '~/repository/components/header_area/fork_suggestion_modal.vue';
import UploadBlobModal from '~/repository/components/upload_blob_modal.vue';
const REPLACE_BLOB_MODAL_ID = 'modal-replace-blob';
@ -18,7 +17,6 @@ export default {
components: {
GlDisclosureDropdownItem,
GlDisclosureDropdownGroup,
ForkSuggestionModal,
UploadBlobModal,
},
mixins: [getRefMixin],
@ -52,11 +50,6 @@ export default {
required: true,
},
},
data() {
return {
isForkSuggestionModalVisible: false,
};
},
computed: {
replaceFileItem() {
return {
@ -77,7 +70,7 @@ export default {
methods: {
showModal() {
if (this.shouldShowForkSuggestion) {
this.isForkSuggestionModalVisible = true;
this.$emit('showForkSuggestion');
return;
}
@ -95,11 +88,6 @@ export default {
data-testid="replace-dropdown-item"
@action="showModal"
/>
<fork-suggestion-modal
:visible="isForkSuggestionModalVisible"
:fork-path="blobInfo.forkAndViewPath"
@hide="isForkSuggestionModalVisible = false"
/>
<upload-blob-modal
:ref="$options.replaceBlobModalId"
:modal-id="$options.replaceBlobModalId"

View File

@ -3,6 +3,7 @@ import { GlButton, GlTooltipDirective } from '@gitlab/ui';
import { computed } from 'vue';
import { __ } from '~/locale';
import { logError } from '~/lib/logger';
import { visitUrl } from '~/lib/utils/url_utility';
import * as Sentry from '~/sentry/sentry_browser_wrapper';
import { createAlert } from '~/alert';
import getRefMixin from '~/repository/mixins/get_ref';
@ -26,6 +27,8 @@ import { updateElementsVisibility } from '~/repository/utils/dom';
import {
showSingleFileEditorForkSuggestion,
showWebIdeForkSuggestion,
isIdeTarget,
forkSuggestionForSelectedEditor,
} from '~/repository/utils/fork_suggestion_utils';
import { showBlameButton, isUsingLfs } from '~/repository/utils/storage_info_utils';
import blobControlsQuery from '~/repository/queries/blob_controls.query.graphql';
@ -34,6 +37,7 @@ import applicationInfoQuery from '~/blob/queries/application_info.query.graphql'
import { getRefType } from '~/repository/utils/ref_type';
import OpenMrBadge from '~/repository/components/header_area/open_mr_badge.vue';
import OverflowMenu from 'ee_else_ce/repository/components/header_area/blob_overflow_menu.vue';
import ForkSuggestionModal from '~/repository/components/header_area/fork_suggestion_modal.vue';
import { TEXT_FILE_TYPE, EMPTY_FILE, DEFAULT_BLOB_INFO } from '../../constants';
export default {
@ -49,6 +53,7 @@ export default {
OpenMrBadge,
GlButton,
OverflowMenu,
ForkSuggestionModal,
WebIdeLink: () => import('ee_else_ce/vue_shared/components/web_ide_link.vue'),
},
directives: {
@ -133,6 +138,7 @@ export default {
project: {},
currentUser: {},
gitpodEnabled: false,
isForkSuggestionModalVisible: false,
};
},
computed: {
@ -247,6 +253,23 @@ export default {
onCopy() {
navigator.clipboard.writeText(this.blobInfo.rawTextBlob);
},
onShowForkSuggestion() {
this.isForkSuggestionModalVisible = true;
},
onEdit(target) {
const { ideEditPath, editBlobPath } = this.blobInfo;
const showForkSuggestionForSelectedEditor = forkSuggestionForSelectedEditor(
target,
this.shouldShowWebIdeForkSuggestion,
this.shouldShowSingleFileEditorForkSuggestion,
);
if (showForkSuggestionForSelectedEditor) {
this.isForkSuggestionModalVisible = true;
} else {
visitUrl(isIdeTarget(target) ? ideEditPath : editBlobPath);
}
},
},
};
</script>
@ -313,7 +336,13 @@ export default {
:user-profile-enable-gitpod-path="currentUser && currentUser.profileEnableGitpodPath"
is-blob
disable-fork-modal
v-on="$listeners"
@edit="onEdit"
/>
<fork-suggestion-modal
v-if="!isLoadingRepositoryBlob"
:visible="isForkSuggestionModalVisible"
:fork-path="blobInfo.forkAndViewPath"
@hide="isForkSuggestionModalVisible = false"
/>
<overflow-menu
@ -324,6 +353,7 @@ export default {
:is-empty-repository="project.repository.empty"
:is-using-lfs="isUsingLfs"
@copy="onCopy"
@showForkSuggestion="onShowForkSuggestion"
/>
</div>
</template>

View File

@ -3,7 +3,6 @@ import { GlDisclosureDropdownGroup, GlDisclosureDropdownItem } from '@gitlab/ui'
import { uniqueId } from 'lodash';
import { sprintf, __ } from '~/locale';
import { showForkSuggestion } from '~/repository/utils/fork_suggestion_utils';
import ForkSuggestionModal from '~/repository/components/header_area/fork_suggestion_modal.vue';
import DeleteBlobModal from '~/repository/components/delete_blob_modal.vue';
import { DEFAULT_BLOB_INFO } from '~/repository/constants';
@ -11,7 +10,6 @@ export default {
components: {
GlDisclosureDropdownGroup,
GlDisclosureDropdownItem,
ForkSuggestionModal,
DeleteBlobModal,
},
inject: {
@ -50,11 +48,6 @@ export default {
default: false,
},
},
data() {
return {
isModalVisible: false,
};
},
computed: {
deleteFileItem() {
return {
@ -82,7 +75,7 @@ export default {
}
if (this.shouldShowForkSuggestion) {
this.isModalVisible = true;
this.$emit('showForkSuggestion');
return;
}
@ -95,11 +88,6 @@ export default {
<template>
<gl-disclosure-dropdown-group bordered>
<gl-disclosure-dropdown-item :item="deleteFileItem" variant="danger" @action="showModal" />
<fork-suggestion-modal
:visible="isModalVisible"
:fork-path="blobInfo.forkAndViewPath"
@hide="isModalVisible = false"
/>
<delete-blob-modal
:ref="deleteModalId"
:delete-path="blobInfo.webPath"

View File

@ -140,6 +140,9 @@ export default {
this.$emit('copy');
}
},
onShowForkSuggestion() {
this.$emit('showForkSuggestion');
},
},
};
</script>
@ -165,6 +168,7 @@ export default {
:can-lock="canLock"
:is-replace-disabled="!canModifyFile"
:is-locked="isLocked"
@showForkSuggestion="onShowForkSuggestion"
/>
<blob-default-actions-group
:active-viewer-type="activeViewerType"
@ -181,6 +185,7 @@ export default {
:is-using-lfs="isUsingLfs"
:user-permissions="userPermissions"
:disabled="!canModifyFile"
@showForkSuggestion="onShowForkSuggestion"
/>
</gl-disclosure-dropdown>
</template>

View File

@ -46,3 +46,31 @@ export const showForkSuggestion = (userPermissions, isUsingLfs, blobInfo) => {
showWebIdeForkSuggestion(userPermissions, isUsingLfs, blobInfo.canModifyBlobWithWebIde)
);
};
/**
* Checks if the target is the Web IDE
* @param {string} target - The target editor ('ide' or 'simple')
* @returns {boolean} - Whether the target is the Web IDE
*/
export const isIdeTarget = (target) => {
return target === 'ide';
};
/**
* Determines which fork suggestion to show based on the selected editor
* Single file editor shows fork suggestion when the ref is not on top of the branch.
* WebIDE does not have this limitation.
* @param {string} target - The target editor ('ide' or 'simple')
* @param {boolean} shouldShowWebIdeForkSuggestion - Whether to show fork suggestion for Web IDE
* @param {boolean} shouldShowSingleFileEditorForkSuggestion - Whether to show fork suggestion for single file editor
* @returns {boolean} - Whether to show fork suggestion for the selected editor
*/
export const forkSuggestionForSelectedEditor = (
target,
shouldShowWebIdeForkSuggestion,
shouldShowSingleFileEditorForkSuggestion,
) => {
return isIdeTarget(target)
? shouldShowWebIdeForkSuggestion
: shouldShowSingleFileEditorForkSuggestion;
};

View File

@ -23,7 +23,6 @@ import {
TODO_WAIT_BEFORE_RELOAD,
TABS_INDICES,
} from '~/todos/constants';
import { setGlobalTodoCount, userCounts } from '~/super_sidebar/user_counts_manager';
import getTodosQuery from './queries/get_todos.query.graphql';
import getPendingTodosCount from './queries/get_pending_todos_count.query.graphql';
import TodoItem from './todo_item.vue';
@ -71,6 +70,7 @@ export default {
pageInfo: {},
todos: [],
currentTab: TABS_INDICES.pending,
pendingTodosCount: '-',
queryFilterValues: {
groupId: [],
projectId: [],
@ -114,24 +114,17 @@ export default {
this.needsRefresh = false;
},
},
// eslint-disable-next-line @gitlab/vue-no-undef-apollo-properties -- The query is not tied to an internal state property
refreshPendingCount: {
pendingTodosCount: {
query: getPendingTodosCount,
variables() {
return this.queryFilterValues;
},
manual: true,
result({ loading, data }) {
if (!loading) {
setGlobalTodoCount(data?.currentUser?.todos?.count);
}
update({ currentUser: { todos: { count } } = {} }) {
return count;
},
},
},
computed: {
pendingTodosCount() {
return userCounts.todos;
},
statusByTab() {
return STATUS_BY_TAB[this.currentTab];
},
@ -294,7 +287,7 @@ export default {
this.updateAllQueries(false);
},
updateCounts() {
return this.$apollo.queries.refreshPendingCount.refetch();
return this.$apollo.queries.pendingTodosCount.refetch();
},
async updateAllQueries(showLoading = true) {
this.$root.$emit('bv::hide::tooltip', 'todo-refresh-btn');

View File

@ -131,8 +131,11 @@ export default {
{{ $options.i18n.steps.step1.help }}
</p>
<pre
:class="$options.userColorScheme"
class="code highlight js-syntax-highlight gl-rounded-base"
:class="[
$options.userColorScheme,
'code highlight js-syntax-highlight gl-rounded-base',
{ 'gl-rounded-b-none': reviewingDocsPath },
]"
data-testid="how-to-merge-instructions"
>{{ mergeInfo1 }}</pre
>

View File

@ -14,7 +14,7 @@
*/
import { GlFormGroup, GlFormInput, GlFormInputGroup, GlLink, GlTooltipDirective } from '@gitlab/ui';
import { uniqueId } from 'lodash';
import { __ } from '~/locale';
import { __, s__ } from '~/locale';
const PREVIEW_COLOR_DEFAULT_CLASSES =
'gl-relative gl-w-7 gl-bg-subtle gl-rounded-tl-base gl-rounded-bl-base';
@ -65,8 +65,8 @@ export default {
computed: {
description() {
return this.hasSuggestedColors
? this.$options.i18n.fullDescription
: this.$options.i18n.shortDescription;
? s__('ColorPicker|Enter any hex color or choose one of the suggested colors below.')
: s__('ColorPicker|Enter any hex color.');
},
previewColor() {
if (this.state) {
@ -90,10 +90,6 @@ export default {
this.$emit('input', color.trim());
},
},
i18n: {
fullDescription: __('Enter any color or choose one of the suggested colors below.'),
shortDescription: __('Enter any color.'),
},
};
</script>
@ -107,15 +103,20 @@ export default {
:state="state"
:class="{ '!gl-mb-3': hasSuggestedColors }"
>
<!-- eslint-disable @gitlab/vue-require-i18n-attribute-strings -->
<gl-form-input-group
:label="label"
max-length="7"
type="text"
class="gl-align-center gl-max-w-26 gl-rounded-none gl-rounded-br-base gl-rounded-tr-base"
:value="value"
placeholder="#RRGGBB"
:state="state"
:aria-labelledby="label"
aria-describedby="color-picker-hint"
@input="handleColorChange"
>
<!-- eslint-enable @gitlab/vue-require-i18n-attribute-strings -->
<template #prepend>
<div :class="previewColorClasses" :style="previewColor" data-testid="color-preview">
<gl-form-input
@ -137,10 +138,13 @@ export default {
:key="hex"
v-gl-tooltip
:title="name"
:aria-label="name"
:style="{ backgroundColor: hex }"
class="gl-mb-3 gl-mr-3 gl-inline-block gl-h-7 gl-w-7 gl-rounded-base gl-no-underline"
@click.prevent="handleColorChange(hex)"
/>
</div>
<span id="color-picker-hint" class="gl-sr-only">{{ description }}</span>
</div>
</template>

View File

@ -0,0 +1,45 @@
<script>
// This component and it's instances should be removed on 4/15/25
// See https://gitlab.com/gitlab-org/gitlab/-/issues/527721
import { GlAlert } from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper';
const DOCKER_HUB_KEY = 'docker_hub_rate_limits_dismissed';
export default {
components: {
GlAlert,
},
data() {
return {
isBannerDismissed: localStorage.getItem(DOCKER_HUB_KEY) === 'true',
};
},
methods: {
handleDismissBanner() {
localStorage.setItem(DOCKER_HUB_KEY, 'true');
this.isBannerDismissed = true;
},
},
authenticatePath: helpPagePath('user/packages/dependency_proxy/_index', {
anchor: 'authenticate-with-docker-hub',
}),
};
</script>
<template>
<gl-alert
v-if="!isBannerDismissed"
variant="warning"
:primary-button-text="__('Authenticate with Docker Hub')"
:primary-button-link="$options.authenticatePath"
:secondary-button-text="__('Learn more')"
secondary-button-link="https://about.gitlab.com/blog/2025/03/24/prepare-now-docker-hub-rate-limits-will-impact-gitlab-ci-cd"
@dismiss="handleDismissBanner"
>
{{
__(
'Docker Hub pull rate limits begin April 1, 2025 and might affect CI/CD pipelines that pull Docker images. To prevent pipeline failures, configure the GitLab Dependency Proxy to authenticate with Docker Hub.',
)
}}
</gl-alert>
</template>

View File

@ -1,18 +0,0 @@
query searchUserGroupProjectsWithMergeRequestsEnabled($fullPath: ID!, $search: String) {
group(fullPath: $fullPath) {
id
projects(
search: $search
withMergeRequestsEnabled: true
includeSubgroups: true
sort: ACTIVITY_DESC
) {
nodes {
id
name
nameWithNamespace
webUrl
}
}
}
}

View File

@ -1 +0,0 @@
The subject will be used as the source branch name for the new merge request and the target branch will be the default branch for the project.

View File

@ -1,8 +0,0 @@
%ul.content-list.mr-list.issuable-list
- if @merge_requests.present?
= render @merge_requests
- else
= render 'shared/empty_states/merge_requests', button_path: new_merge_request_path
- if @merge_requests.present?
= paginate_collection @merge_requests, total_pages: @total_pages

View File

@ -7,6 +7,8 @@
%h1.gl-sr-only= @breadcrumb_title
#js-docker-hub-rate-limits-alert
- if can?(current_user, :admin_pipeline, @project)
= render ::Layouts::SettingsBlockComponent.new(_("General pipelines"),
id: 'js-general-pipeline-settings',

View File

@ -8,7 +8,7 @@ class GitlabServicePingWorker # rubocop:disable Scalability/IdempotentWorker
include ApplicationWorker
data_consistency :always
data_consistency :sticky
include CronjobQueue # rubocop:disable Scalability/CronWorkerContext
include Gitlab::ExclusiveLeaseHelpers

View File

@ -1,6 +1,6 @@
- title: 'Registration tokens and server-side runner arguments in `POST /api/v4/runners` endpoint' # (required) The name of the feature to be deprecated
announcement_milestone: '15.6' # (required) The milestone when this feature was first announced as deprecated.
removal_milestone: '18.0' # (required) The milestone when this feature is planned to be removed
removal_milestone: '20.0' # (required) The milestone when this feature is planned to be removed
breaking_change: true # (required) If this deprecation is a breaking change, set this value to true
reporter: pedropombeiro # (required) GitLab username of the person reporting the deprecation
stage: Verify # (required) String value of the stage that the feature was created in. e.g., Growth
@ -13,7 +13,8 @@
body: | # (required) Do not modify this line, instead modify the lines below.
The support for registration tokens and certain runner configuration arguments in the `POST` method operation on the `/api/v4/runners` endpoint is deprecated.
This endpoint [registers](https://docs.gitlab.com/api/runners/#create-a-runner) a runner
with a GitLab instance at the instance, group, or project level through the API. In GitLab 18.0, registration tokens, and support for certain configuration arguments,
with a GitLab instance at the instance, group, or project level through the API.
In a future GitLab major release, registration tokens, and support for certain configuration arguments,
will start returning the HTTP `410 Gone` status code. For more information, see [Migrating to the new runner registration workflow](https://docs.gitlab.com/ci/runners/new_creation_workflow/#prevent-your-runner-registration-workflow-from-breaking).
The configuration arguments disabled for runner authentication tokens are:

View File

@ -1,7 +1,6 @@
- title: "`runnerRegistrationToken` parameter for GitLab Runner Helm Chart" # (required) The name of the feature to be deprecated
announcement_milestone: "15.6" # (required) The milestone when this feature was first announced as deprecated.
removal_milestone: "18.0" # (required) The milestone when this feature is planned to be removed
removal_date: "2025-04-22"
removal_milestone: "20.0" # (required) The milestone when this feature is planned to be removed
breaking_change: true # (required) If this deprecation is a breaking change, set this value to true
reporter: pedropombeiro # (required) GitLab username of the person reporting the deprecation
stage: Verify # (required) String value of the stage that the feature was created in. e.g., Growth
@ -18,5 +17,5 @@
as part of the new [GitLab Runner token architecture](https://docs.gitlab.com/ci/runners/new_creation_workflow/).
The work is planned in [this epic](https://gitlab.com/groups/gitlab-org/-/epics/7633).
From GitLab 18.0 and later, the methods to register runners introduced by the new GitLab Runner token architecture will be the only supported methods.
In a future GitLab release, the methods to register runners introduced by the new GitLab Runner token architecture will be the only supported methods.
end_of_support_milestone: # (optional) Use "XX.YY" format. The milestone when support for this feature will end.

View File

@ -1,7 +1,6 @@
- title: "Registration tokens and server-side runner arguments in `gitlab-runner register` command" # (required) The name of the feature to be deprecated
announcement_milestone: "15.6" # (required) The milestone when this feature was first announced as deprecated.
removal_milestone: "18.0" # (required) The milestone when this feature is planned to be removed
removal_date: "2025-04-22"
removal_milestone: "20.0" # (required) The milestone when this feature is planned to be removed
breaking_change: true # (required) If this deprecation is a breaking change, set this value to true
reporter: pedropombeiro # (required) GitLab username of the person reporting the deprecation
stage: Verify # (required) String value of the stage that the feature was created in. e.g., Growth
@ -14,7 +13,7 @@
body: | # (required) Do not modify this line, instead modify the lines below.
Registration tokens and certain configuration arguments in the command `gitlab-runner register` that [registers](https://docs.gitlab.com/runner/register/) a runner, are deprecated.
Authentication tokens will be used to register runners instead. Registration tokens, and support for certain configuration arguments,
will be removed in GitLab 18.0. For more information, see [Migrating to the new runner registration workflow](https://docs.gitlab.com/ci/runners/new_creation_workflow/).
will be removed in a future GitLab release. For more information, see [Migrating to the new runner registration workflow](https://docs.gitlab.com/ci/runners/new_creation_workflow/).
The configuration arguments disabled for authentication tokens are:
- `--locked`

View File

@ -1,14 +1,13 @@
- title: "GitLab Runner registration token in Runner Operator" # (required) The name of the feature to be deprecated
announcement_milestone: "15.6" # (required) The milestone when this feature was first announced as deprecated.
removal_milestone: "18.0" # (required) The milestone when this feature is planned to be removed
removal_date: "2025-04-22"
removal_milestone: "20.0" # (required) The milestone when this feature is planned to be removed
breaking_change: true # (required) If this deprecation is a breaking change, set this value to true
reporter: ratchade # (required) GitLab username of the person reporting the deprecation
stage: Verify # (required) String value of the stage that the feature was created in. e.g., Growth
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/382077 # (required) Link to the deprecation issue in GitLab
body: | # (required) Do not modify this line, instead modify the lines below.
The [`runner-registration-token`](https://docs.gitlab.com/runner/install/operator/#install-the-kubernetes-operator) parameter that uses the OpenShift and Kubernetes Vanilla Operator to install a runner on Kubernetes is deprecated. Authentication tokens will be used to register runners instead. Registration tokens, and support for certain configuration arguments,
will be removed in GitLab 18.0. For more information, see [Migrating to the new runner registration workflow](https://docs.gitlab.com/ci/runners/new_creation_workflow/).
will be removed in a future GitLab release. For more information, see [Migrating to the new runner registration workflow](https://docs.gitlab.com/ci/runners/new_creation_workflow/).
The configuration arguments disabled for authentication tokens are:
- `--locked`

View File

@ -1,7 +1,6 @@
- title: "Support for REST API endpoints that reset runner registration tokens" # (required) The name of the feature to be deprecated
announcement_milestone: "15.7" # (required) The milestone when this feature was first announced as deprecated.
removal_milestone: "18.0" # (required) The milestone when this feature is planned to be removed
removal_date: "2025-04-22"
removal_milestone: "20.0" # (required) The milestone when this feature is planned to be removed
breaking_change: true # (required) If this deprecation is a breaking change, set this value to true
reporter: pedropombeiro # (required) GitLab username of the person reporting the deprecation
stage: Verify # (required) String value of the stage that the feature was created in. e.g., Growth
@ -13,7 +12,7 @@
window: "1"
body: | # (required) Do not modify this line, instead modify the lines below.
The support for runner registration tokens is deprecated. As a consequence, the REST API endpoints to reset a registration token are also deprecated and will
return the HTTP `410 Gone` status code in GitLab 18.0.
return the HTTP `410 Gone` status code in a future GitLab release.
The deprecated endpoints are:
- `POST /runners/reset_registration_token`
@ -25,7 +24,7 @@
The work is planned in [this epic](https://gitlab.com/groups/gitlab-org/-/epics/7633).
This new architecture introduces a new method for registering runners and will eliminate the legacy
[runner registration token](https://docs.gitlab.com/security/tokens/#runner-registration-tokens-deprecated).
From GitLab 18.0 and later, the runner registration methods implemented by the new GitLab Runner token architecture will be the only supported methods.
In a future GitLab release, the runner registration methods implemented by the new GitLab Runner token architecture will be the only supported methods.
end_of_support_milestone: # (optional) Use "XX.YY" format. The milestone when support for this feature will end.
tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
documentation_url: https://docs.gitlab.com/api/runners/#create-a-runner # (optional) This is a link to the current documentation page

View File

@ -1,7 +1,6 @@
- title: 'GitLab Runner platforms and setup instructions in GraphQL API'
announcement_milestone: '15.9'
announcement_date: '2023-02-22'
removal_milestone: '18.0'
removal_milestone: '20.0'
breaking_change: true
reporter: mrincon
body: |

View File

@ -1,6 +1,6 @@
- title: '`GITLAB_SHARED_RUNNERS_REGISTRATION_TOKEN` is deprecated'
# The milestones for the deprecation announcement, and the removal.
removal_milestone: '18.0'
removal_milestone: '20.0'
announcement_milestone: '16.11'
# Change breaking_change to false if needed.
breaking_change: true

View File

@ -1,6 +1,6 @@
- title: "RunnersRegistrationTokenReset GraphQL mutation is deprecated"
# The milestones for the deprecation announcement, and the removal.
removal_milestone: "18.0"
removal_milestone: "20.0"
announcement_milestone: "17.7"
breaking_change: true
window: "2"
@ -14,14 +14,14 @@
manual_task: true
body: | # (required) Don't change this line.
The support for runner registration tokens is deprecated. Consequently, the support for resetting a registration token has also been deprecated
and will be removed in GitLab 18.0.
and will be removed in a future GitLab release.
A new method to bind runners to a GitLab instance has been implemented
as part of the new [GitLab Runner token architecture](https://docs.gitlab.com/ci/runners/new_creation_workflow/).
For details, see [epic 7633](https://gitlab.com/groups/gitlab-org/-/epics/7633).
This new architecture introduces a new method for registering runners and eliminates the legacy
[runner registration token](https://docs.gitlab.com/security/tokens/#runner-registration-tokens-deprecated).
In GitLab 18.0, only the runner registration methods implemented in the new GitLab Runner token architecture will be supported.
In a future GitLab release, only the runner registration methods implemented in the new GitLab Runner token architecture will be supported.
#
# When support for this feature ends, in XX.YY milestone format.
end_of_support_milestone:

View File

@ -0,0 +1,8 @@
---
migration_job_name: BackfillExternalGroupAuditEventDestinations
description: Backfill the audit_events_external_audit_event_destinations table to audit_events_group_external_streaming_destinations
feature_category: audit_events
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/183044
milestone: '17.11'
queued_migration_version: 20250310144538
finalized_by: # version of the migration that finalized this BBM

View File

@ -0,0 +1,53 @@
# frozen_string_literal: true
class EnsureRunnerTaggingsExist < Gitlab::Database::Migration[2.2]
milestone '17.9'
disable_ddl_transaction!
restrict_gitlab_migration gitlab_schema: :gitlab_ci
BATCH_SIZE = 500
class CiRunnerMigration < MigrationRecord
include ::EachBatch
self.primary_key = :id
end
def up
return unless new_taggings_table_is_empty?
CiRunnerMigration.table_name = find_new_runners_table_name
CiRunnerMigration.each_batch(of: BATCH_SIZE) do |batch|
scope = batch
.joins("inner join taggings on #{CiRunnerMigration.quoted_table_name}.id = taggings.taggable_id")
.where(taggings: { taggable_type: 'Ci::Runner' })
.select(:tag_id, 'taggable_id as runner_id', :sharding_key_id, :runner_type)
connection.execute(<<~SQL.squish)
INSERT INTO ci_runner_taggings(tag_id, runner_id, sharding_key_id, runner_type)
(#{scope.to_sql})
ON CONFLICT DO NOTHING;
SQL
end
end
def down; end
private
# Even though we introduce this at a specific timestamp,
# it could still be executed from a patch release in which the table
# was already renamed.
def find_new_runners_table_name
if connection.table_exists?(:ci_runners_e59bb2812d)
:ci_runners_e59bb2812d
else
:ci_runners
end
end
def new_taggings_table_is_empty?
!connection.select_value('SELECT true FROM ci_runner_taggings LIMIT 1')
end
end

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
class QueueUpdatePackageNameInPmAffectedPackages < Gitlab::Database::Migration[2.2]
milestone '17.11'
restrict_gitlab_migration gitlab_schema: :gitlab_pm
def up
execute <<~SQL
UPDATE pm_affected_packages SET package_name = REGEXP_REPLACE(LOWER(package_name), '[-_.]+', '-')
WHERE purl_type = 8
AND package_name != REGEXP_REPLACE(LOWER(package_name), '[-_.]+', '-')
AND NOT EXISTS (
SELECT 1 FROM pm_affected_packages as target
WHERE target.purl_type = pm_affected_packages.purl_type
AND target.package_name = REGEXP_REPLACE(LOWER(pm_affected_packages.package_name), '[-_.]+', '-')
AND target.pm_advisory_id = pm_affected_packages.pm_advisory_id
AND target.distro_version = pm_affected_packages.distro_version
)
SQL
end
def down
# No-op
end
end

View File

@ -0,0 +1,27 @@
# frozen_string_literal: true
class QueueBackfillExternalGroupAuditEventDestinations < Gitlab::Database::Migration[2.2]
milestone '17.11'
restrict_gitlab_migration gitlab_schema: :gitlab_main
MIGRATION = "BackfillExternalGroupAuditEventDestinations"
DELAY_INTERVAL = 2.minutes
BATCH_SIZE = 1000
SUB_BATCH_SIZE = 100
def up
queue_batched_background_migration(
MIGRATION,
:audit_events_external_audit_event_destinations,
: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_external_audit_event_destinations, :id, [])
end
end

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
class DropVirtualRegistriesPackagesMavenRegistriesCacheValidityHours < Gitlab::Database::Migration[2.2]
disable_ddl_transaction!
milestone '17.11'
TABLE_NAME = :virtual_registries_packages_maven_registries
def up
remove_column TABLE_NAME, :cache_validity_hours, if_exists: true
end
def down
add_column TABLE_NAME, :cache_validity_hours, :smallint, null: false, default: 1, if_not_exists: true
constraint_name = check_constraint_name(TABLE_NAME.to_s, 'cache_validity_hours', 'zero_or_positive')
add_check_constraint(TABLE_NAME, 'cache_validity_hours >= 0', constraint_name)
end
end

View File

@ -0,0 +1 @@
9350aa08bf40369cee7a2c98a1d57259d00c81c7f8afa0d49a9576f61bc356dc

View File

@ -0,0 +1 @@
657aab63d4b58bdfef82812ff1bc397cafc7a313b484a22084dc3b238db06f0c

View File

@ -0,0 +1 @@
52a7525c092bc9fa9ed7695258903276784c050e63d48cafe229269383b5efc8

View File

@ -0,0 +1 @@
b85ee2bfed01abe0c07a61fe94f45c5202b2773fcc023550a5dca67f4c5f1bae

View File

@ -24371,9 +24371,7 @@ CREATE TABLE virtual_registries_packages_maven_registries (
id bigint NOT NULL,
group_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
cache_validity_hours smallint DEFAULT 1 NOT NULL,
CONSTRAINT check_b3fbe8eb62 CHECK ((cache_validity_hours >= 0))
updated_at timestamp with time zone NOT NULL
);
CREATE SEQUENCE virtual_registries_packages_maven_registries_id_seq

View File

@ -59,3 +59,21 @@ Each Sunday night in UTC, Switchboard updates to display the planned GitLab vers
## Hosted runners
The **Hosted runners** section shows the [hosted runners](hosted_runners.md) associated with your instance.
## NAT IP addresses
NAT gateway IP addresses typically remain consistent during standard operations but might change occasionally, such as when GitLab needs to rebuild your instance during disaster recovery.
You need to know your NAT gateway IP addresses in cases like:
- Configuring webhook receivers to accept incoming requests from your GitLab Dedicated instance.
- Setting up allowlists for external services to accept connections from your GitLab Dedicated instance.
### View your NAT gateway IP addresses
To view the current NAT gateway IP addresses for your GitLab Dedicated instance:
1. Sign in to [Switchboard](https://console.gitlab-dedicated.com/).
1. Select your tenant.
1. Select the **Configuration** tab.
1. Under **Tenant Details**, find your **NAT gateways**.

View File

@ -380,7 +380,7 @@ parameter in the `projects` REST API endpoint.
## Fine-grained permissions for job tokens
Fine-grained permissions for job tokens are an [experiment](../../policy/development_stages_support.md#experiment). For information on this feature and the available resources, see [Fine-grained permissions for CI/CD job tokens](fine_grained_permissions.md). Feedback is welcome on this [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/519575).
Fine-grained permissions for job tokens are an [experiment](../../policy/development_stages_support.md#experiment). For information on this feature and the available resources, see [fine-grained permissions for CI/CD job tokens](fine_grained_permissions.md). Feedback is welcome on this [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/519575).
## Use a job token

View File

@ -34,7 +34,7 @@ These permissions are applied to the CI/CD job tokens in a specified project.
This feature is an [experiment](../../policy/development_stages_support.md#experiment) and subject to change without notice. This feature is not ready for production use. If you want to use this feature, you should test outside of production first.
## Enable fine-grained permissions for projects
## Enable use of fine-grained permissions
Prerequisites:
@ -50,6 +50,32 @@ To enable fine-grained permissions for all projects in a group:
1. Expand **General pipelines**.
1. Turn on the **Enable fine-grained permissions for CI/CD job tokens** toggle.
## Add fine-grained permissions to the job token allowlist
Prerequisites:
- You must have at least the Maintainer role for the project.
- You must enable the use of fine-grained permissions for a project.
You can add fine-grained permissions to groups and projects on your job token allowlist. This allows
them to use job tokens to access specific project resources and more accurately control which
resources are available to these groups and projects.
To add fine-grained permissions to groups or projects on the job token allowlist:
1. On the left sidebar, select **Search or go to** and find your project.
1. Select **Settings > CI/CD**.
1. Expand **Job token permissions**.
1. In the **CI/CD job token allowlist** section, select **Add**.
1. From the dropdown list, select **Group or project**.
1. Enter the path to an existing group or project.
1. Select **Fine-grained permissions**.
1. Grant permissions to the [available API endpoints](#available-api-endpoints).
1. Select **Add**.
GitLab adds the group or project to the job token allowlist with the specified permissions. The group or project can now
access any allowed resources in the current project.
## Available API endpoints
The following endpoints are available for CI/CD job tokens.

View File

@ -93,7 +93,7 @@ The runner authentication tokens are recognizable by their `glrt-` prefix.
When you create a runner in the GitLab UI, you specify configuration values that were previously command-line options
prompted by the `gitlab-runner register` command.
These command-line options have been [deprecated](../../update/deprecations.md#registration-tokens-and-server-side-runner-arguments-in-post-apiv4runners-endpoint).
These command-line options will be deprecated in the future.
If you specify a runner authentication token with:

View File

@ -24,11 +24,6 @@ This window takes place on April 21 - 23, 2025 from 09:00 UTC to 22:00 UTC.
| Deprecation | Impact | Stage | Scope |
|-------------|--------|-------|-------|
| [Registration tokens and server-side runner arguments in `POST /api/v4/runners` endpoint](https://gitlab.com/gitlab-org/gitlab/-/issues/379743) | Critical | Verify | Instance, group, project |
| [`runnerRegistrationToken` parameter for GitLab Runner Helm Chart](https://gitlab.com/gitlab-org/gitlab/-/issues/381111) | Critical | Verify | Instance, group, project |
| [Registration tokens and server-side runner arguments in `gitlab-runner register` command](https://gitlab.com/gitlab-org/gitlab/-/issues/380872) | Critical | Verify | Instance, group, project |
| [Support for REST API endpoints that reset runner registration tokens](https://gitlab.com/gitlab-org/gitlab/-/issues/383341) | Critical | Verify | Instance, group, project |
| [GitLab Runner platforms and setup instructions in GraphQL API](https://gitlab.com/gitlab-org/gitlab/-/issues/387937) | Low | Verify | Instance, group, project |
| [CI/CD job token - **Limit access from your project** setting removal](https://gitlab.com/gitlab-org/gitlab/-/issues/395708) | High | Verify | Project |
| [CI/CD job token - **Authorized groups and projects** allowlist enforcement](https://gitlab.com/gitlab-org/gitlab/-/issues/383084) | High | Govern | Project |
| [Deprecate License Scanning CI/CD artifact report type](https://gitlab.com/gitlab-org/gitlab/-/issues/439301) | Low | Secure | Project |
@ -64,11 +59,9 @@ This window takes place on April 28 - 30, 2025 from 09:00 UTC to 22:00 UTC.
| Deprecation | Impact | Stage | Scope |
|-------------|--------|-------|-------|
| [Replace GraphQL field `take_ownership_pipeline_schedule` with `admin_pipeline_schedule` in PipelineSchedulePermissions](https://gitlab.com/gitlab-org/gitlab/-/issues/391941) | Low | Verify | Project |
| [`GITLAB_SHARED_RUNNERS_REGISTRATION_TOKEN` is deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/453949) | Medium | Verify | Instance |
| [The `heroku/builder:22` image is deprecated](https://gitlab.com/gitlab-org/cluster-integration/auto-build-image/-/issues/79) | Medium | Deploy | Project |
| [`ciMinutesUsed` GraphQL field renamed to `ciDuration`](https://gitlab.com/gitlab-org/gitlab/-/issues/497364) | Medium | Verify | Instance |
| [`mergeTrainIndex` and `mergeTrainsCount` GraphQL fields deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/473759) | Low | Verify | Project |
| [RunnersRegistrationTokenReset GraphQL mutation is deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/505703) | High | Verify | Instance, group, project |
| [Behavior change for Upcoming and Started milestone filters](https://gitlab.com/gitlab-org/gitlab/-/issues/501294) | Low | Plan | Group, project |
| [`kpt`-based `agentk` is deprecated](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/issues/656) | Low | Deploy | Project |
| [Updating CI/CD job tokens to JWT standard](https://gitlab.com/gitlab-org/gitlab/-/issues/509578) | | Software supply chain security | |

View File

@ -65,6 +65,203 @@ For deprecation reviewers (Technical Writers only):
The [GitLab Runner Docker Machine executor](https://docs.gitlab.com/runner/executors/docker_machine/) is deprecated and will be fully removed from the product as a supported feature in GitLab 20.0 (May 2027). The replacement for Docker Machine, [GitLab Runner Autoscaler](https://docs.gitlab.com/runner/runner_autoscale/) with GitLab developed plugins for Amazon Web Services (AWS) EC2, Google Compute Engine (GCE) and Microsoft Azure virtual machines (VMs) is generally available. With this announcement, the GitLab Runner team will no longer accept community contributions for the GitLab maintained Docker Machine fork, or resolve newly identified bugs.
</div>
<div class="deprecation breaking-change" data-milestone="20.0">
### GitLab Runner platforms and setup instructions in GraphQL API
<div class="deprecation-notes">
- Announced in GitLab <span class="milestone">15.9</span>
- Removal in GitLab <span class="milestone">20.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/gitlab-org/gitlab/-/issues/387937).
</div>
The `runnerPlatforms` and `runnerSetup` queries to get GitLab Runner platforms and installation instructions
are deprecated and will be removed from the GraphQL API. For installation instructions, you should use the
[GitLab Runner documentation](https://docs.gitlab.com/runner/)
</div>
<div class="deprecation breaking-change" data-milestone="20.0">
### GitLab Runner registration token in Runner Operator
<div class="deprecation-notes">
- Announced in GitLab <span class="milestone">15.6</span>
- Removal in GitLab <span class="milestone">20.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/gitlab-org/gitlab/-/issues/382077).
</div>
The [`runner-registration-token`](https://docs.gitlab.com/runner/install/operator/#install-the-kubernetes-operator) parameter that uses the OpenShift and Kubernetes Vanilla Operator to install a runner on Kubernetes is deprecated. Authentication tokens will be used to register runners instead. Registration tokens, and support for certain configuration arguments,
will be removed in a future GitLab release. For more information, see [Migrating to the new runner registration workflow](https://docs.gitlab.com/ci/runners/new_creation_workflow/).
The configuration arguments disabled for authentication tokens are:
- `--locked`
- `--access-level`
- `--run-untagged`
- `--tag-list`
This change is a breaking change. You must use an [authentication token](https://docs.gitlab.com/ci/runners/runners_scope/) in the `gitlab-runner register` command instead.
See also how to [prevent your runner registration workflow from breaking](https://docs.gitlab.com/ci/runners/new_creation_workflow/#prevent-your-runner-registration-workflow-from-breaking) in GitLab 17.0 and later.
</div>
<div class="deprecation breaking-change" data-milestone="20.0">
### Registration tokens and server-side runner arguments in `POST /api/v4/runners` endpoint
<div class="deprecation-notes">
- Announced in GitLab <span class="milestone">15.6</span>
- Removal in GitLab <span class="milestone">20.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/gitlab-org/gitlab/-/issues/379743).
</div>
The support for registration tokens and certain runner configuration arguments in the `POST` method operation on the `/api/v4/runners` endpoint is deprecated.
This endpoint [registers](https://docs.gitlab.com/api/runners/#create-a-runner) a runner
with a GitLab instance at the instance, group, or project level through the API.
In a future GitLab major release, registration tokens, and support for certain configuration arguments,
will start returning the HTTP `410 Gone` status code. For more information, see [Migrating to the new runner registration workflow](https://docs.gitlab.com/ci/runners/new_creation_workflow/#prevent-your-runner-registration-workflow-from-breaking).
The configuration arguments disabled for runner authentication tokens are:
- `--locked`
- `--access-level`
- `--run-untagged`
- `--maximum-timeout`
- `--paused`
- `--tag-list`
- `--maintenance-note`
This change is a breaking change. You should [create a runner in the UI](https://docs.gitlab.com/ci/runners/runners_scope/) to add configurations, and use the runner authentication token in the `gitlab-runner register` command instead.
</div>
<div class="deprecation breaking-change" data-milestone="20.0">
### Registration tokens and server-side runner arguments in `gitlab-runner register` command
<div class="deprecation-notes">
- Announced in GitLab <span class="milestone">15.6</span>
- Removal in GitLab <span class="milestone">20.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/gitlab-org/gitlab/-/issues/380872).
</div>
Registration tokens and certain configuration arguments in the command `gitlab-runner register` that [registers](https://docs.gitlab.com/runner/register/) a runner, are deprecated.
Authentication tokens will be used to register runners instead. Registration tokens, and support for certain configuration arguments,
will be removed in a future GitLab release. For more information, see [Migrating to the new runner registration workflow](https://docs.gitlab.com/ci/runners/new_creation_workflow/).
The configuration arguments disabled for authentication tokens are:
- `--locked`
- `--access-level`
- `--run-untagged`
- `--maximum-timeout`
- `--paused`
- `--tag-list`
- `--maintenance-note`
This change is a breaking change. You should [create a runner in the UI](https://docs.gitlab.com/ci/runners/runners_scope/) to add configurations, and use the authentication token in the `gitlab-runner register` command instead.
</div>
<div class="deprecation breaking-change" data-milestone="20.0">
### RunnersRegistrationTokenReset GraphQL mutation is deprecated
<div class="deprecation-notes">
- Announced in GitLab <span class="milestone">17.7</span>
- Removal in GitLab <span class="milestone">20.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/gitlab-org/gitlab/-/issues/505703).
</div>
The support for runner registration tokens is deprecated. Consequently, the support for resetting a registration token has also been deprecated
and will be removed in a future GitLab release.
A new method to bind runners to a GitLab instance has been implemented
as part of the new [GitLab Runner token architecture](https://docs.gitlab.com/ci/runners/new_creation_workflow/).
For details, see [epic 7633](https://gitlab.com/groups/gitlab-org/-/epics/7633).
This new architecture introduces a new method for registering runners and eliminates the legacy
[runner registration token](https://docs.gitlab.com/security/tokens/#runner-registration-tokens-deprecated).
In a future GitLab release, only the runner registration methods implemented in the new GitLab Runner token architecture will be supported.
</div>
<div class="deprecation breaking-change" data-milestone="20.0">
### Support for REST API endpoints that reset runner registration tokens
<div class="deprecation-notes">
- Announced in GitLab <span class="milestone">15.7</span>
- Removal in GitLab <span class="milestone">20.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/gitlab-org/gitlab/-/issues/383341).
</div>
The support for runner registration tokens is deprecated. As a consequence, the REST API endpoints to reset a registration token are also deprecated and will
return the HTTP `410 Gone` status code in a future GitLab release.
The deprecated endpoints are:
- `POST /runners/reset_registration_token`
- `POST /projects/:id/runners/reset_registration_token`
- `POST /groups/:id/runners/reset_registration_token`
We plan to implement a new method to bind runners to a GitLab instance
as part of the new [GitLab Runner token architecture](https://docs.gitlab.com/ci/runners/new_creation_workflow/).
The work is planned in [this epic](https://gitlab.com/groups/gitlab-org/-/epics/7633).
This new architecture introduces a new method for registering runners and will eliminate the legacy
[runner registration token](https://docs.gitlab.com/security/tokens/#runner-registration-tokens-deprecated).
In a future GitLab release, the runner registration methods implemented by the new GitLab Runner token architecture will be the only supported methods.
</div>
<div class="deprecation breaking-change" data-milestone="20.0">
### `GITLAB_SHARED_RUNNERS_REGISTRATION_TOKEN` is deprecated
<div class="deprecation-notes">
- Announced in GitLab <span class="milestone">16.11</span>
- Removal in GitLab <span class="milestone">20.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/gitlab-org/gitlab/-/issues/453949).
</div>
The [`GITLAB_SHARED_RUNNERS_REGISTRATION_TOKEN`](https://docs.gitlab.com/administration/environment_variables/#supported-environment-variables) environment variable is deprecated. GitLab introduced a new [GitLab Runner token architecture](https://docs.gitlab.com/architecture/blueprints/runner_tokens/) in GitLab 15.8, which introduces a new method for registering runners and eliminates the legacy runner registration token. Please refer to the [documentation](https://docs.gitlab.com/ci/runners/new_creation_workflow/) for guidance on migrating to the new workflow.
</div>
<div class="deprecation breaking-change" data-milestone="20.0">
### `runnerRegistrationToken` parameter for GitLab Runner Helm Chart
<div class="deprecation-notes">
- Announced in GitLab <span class="milestone">15.6</span>
- Removal in GitLab <span class="milestone">20.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/gitlab-org/gitlab/-/issues/381111).
</div>
The [`runnerRegistrationToken`](https://docs.gitlab.com/runner/install/kubernetes/) parameter to use the GitLab Helm Chart to install a runner on Kubernetes is deprecated.
We plan to implement a new method to bind runners to a GitLab instance leveraging `runnerToken`
as part of the new [GitLab Runner token architecture](https://docs.gitlab.com/ci/runners/new_creation_workflow/).
The work is planned in [this epic](https://gitlab.com/groups/gitlab-org/-/epics/7633).
In a future GitLab release, the methods to register runners introduced by the new GitLab Runner token architecture will be the only supported methods.
</div>
</div>
@ -1076,51 +1273,6 @@ You can set this variable in your project, group, or policy now to prevent Advan
</div>
<div class="deprecation breaking-change" data-milestone="18.0">
### GitLab Runner platforms and setup instructions in GraphQL API
<div class="deprecation-notes">
- Announced in GitLab <span class="milestone">15.9</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/gitlab-org/gitlab/-/issues/387937).
</div>
The `runnerPlatforms` and `runnerSetup` queries to get GitLab Runner platforms and installation instructions
are deprecated and will be removed from the GraphQL API. For installation instructions, you should use the
[GitLab Runner documentation](https://docs.gitlab.com/runner/)
</div>
<div class="deprecation breaking-change" data-milestone="18.0">
### GitLab Runner registration token in Runner Operator
<div class="deprecation-notes">
- Announced in GitLab <span class="milestone">15.6</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/gitlab-org/gitlab/-/issues/382077).
</div>
The [`runner-registration-token`](https://docs.gitlab.com/runner/install/operator/#install-the-kubernetes-operator) parameter that uses the OpenShift and Kubernetes Vanilla Operator to install a runner on Kubernetes is deprecated. Authentication tokens will be used to register runners instead. Registration tokens, and support for certain configuration arguments,
will be removed in GitLab 18.0. For more information, see [Migrating to the new runner registration workflow](https://docs.gitlab.com/ci/runners/new_creation_workflow/).
The configuration arguments disabled for authentication tokens are:
- `--locked`
- `--access-level`
- `--run-untagged`
- `--tag-list`
This change is a breaking change. You must use an [authentication token](https://docs.gitlab.com/ci/runners/runners_scope/) in the `gitlab-runner register` command instead.
See also how to [prevent your runner registration workflow from breaking](https://docs.gitlab.com/ci/runners/new_creation_workflow/#prevent-your-runner-registration-workflow-from-breaking) in GitLab 17.0 and later.
</div>
<div class="deprecation " data-milestone="18.0">
### GitLab Runner support for Alpine versions
@ -1610,66 +1762,6 @@ Instance administrators can set higher or lower limits as needed in the Admin ar
<div class="deprecation breaking-change" data-milestone="18.0">
### Registration tokens and server-side runner arguments in `POST /api/v4/runners` endpoint
<div class="deprecation-notes">
- Announced in GitLab <span class="milestone">15.6</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/gitlab-org/gitlab/-/issues/379743).
</div>
The support for registration tokens and certain runner configuration arguments in the `POST` method operation on the `/api/v4/runners` endpoint is deprecated.
This endpoint [registers](https://docs.gitlab.com/api/runners/#create-a-runner) a runner
with a GitLab instance at the instance, group, or project level through the API. In GitLab 18.0, registration tokens, and support for certain configuration arguments,
will start returning the HTTP `410 Gone` status code. For more information, see [Migrating to the new runner registration workflow](https://docs.gitlab.com/ci/runners/new_creation_workflow/#prevent-your-runner-registration-workflow-from-breaking).
The configuration arguments disabled for runner authentication tokens are:
- `--locked`
- `--access-level`
- `--run-untagged`
- `--maximum-timeout`
- `--paused`
- `--tag-list`
- `--maintenance-note`
This change is a breaking change. You should [create a runner in the UI](https://docs.gitlab.com/ci/runners/runners_scope/) to add configurations, and use the runner authentication token in the `gitlab-runner register` command instead.
</div>
<div class="deprecation breaking-change" data-milestone="18.0">
### Registration tokens and server-side runner arguments in `gitlab-runner register` command
<div class="deprecation-notes">
- Announced in GitLab <span class="milestone">15.6</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/gitlab-org/gitlab/-/issues/380872).
</div>
Registration tokens and certain configuration arguments in the command `gitlab-runner register` that [registers](https://docs.gitlab.com/runner/register/) a runner, are deprecated.
Authentication tokens will be used to register runners instead. Registration tokens, and support for certain configuration arguments,
will be removed in GitLab 18.0. For more information, see [Migrating to the new runner registration workflow](https://docs.gitlab.com/ci/runners/new_creation_workflow/).
The configuration arguments disabled for authentication tokens are:
- `--locked`
- `--access-level`
- `--run-untagged`
- `--maximum-timeout`
- `--paused`
- `--tag-list`
- `--maintenance-note`
This change is a breaking change. You should [create a runner in the UI](https://docs.gitlab.com/ci/runners/runners_scope/) to add configurations, and use the authentication token in the `gitlab-runner register` command instead.
</div>
<div class="deprecation breaking-change" data-milestone="18.0">
### Reject container image pull policies not in `allowed_pull_policies`
<div class="deprecation-notes">
@ -1871,30 +1963,6 @@ Occurrences of the `active` identifier in the GitLab GraphQL API endpoints will
<div class="deprecation breaking-change" data-milestone="18.0">
### RunnersRegistrationTokenReset GraphQL mutation is deprecated
<div class="deprecation-notes">
- Announced in GitLab <span class="milestone">17.7</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/gitlab-org/gitlab/-/issues/505703).
</div>
The support for runner registration tokens is deprecated. Consequently, the support for resetting a registration token has also been deprecated
and will be removed in GitLab 18.0.
A new method to bind runners to a GitLab instance has been implemented
as part of the new [GitLab Runner token architecture](https://docs.gitlab.com/ci/runners/new_creation_workflow/).
For details, see [epic 7633](https://gitlab.com/groups/gitlab-org/-/epics/7633).
This new architecture introduces a new method for registering runners and eliminates the legacy
[runner registration token](https://docs.gitlab.com/security/tokens/#runner-registration-tokens-deprecated).
In GitLab 18.0, only the runner registration methods implemented in the new GitLab Runner token architecture will be supported.
</div>
<div class="deprecation breaking-change" data-milestone="18.0">
### SAST jobs no longer use global cache settings
<div class="deprecation-notes">
@ -1974,35 +2042,6 @@ You shouldn't experience any impact as a result of this change, as these are end
<div class="deprecation breaking-change" data-milestone="18.0">
### Support for REST API endpoints that reset runner registration tokens
<div class="deprecation-notes">
- Announced in GitLab <span class="milestone">15.7</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/gitlab-org/gitlab/-/issues/383341).
</div>
The support for runner registration tokens is deprecated. As a consequence, the REST API endpoints to reset a registration token are also deprecated and will
return the HTTP `410 Gone` status code in GitLab 18.0.
The deprecated endpoints are:
- `POST /runners/reset_registration_token`
- `POST /projects/:id/runners/reset_registration_token`
- `POST /groups/:id/runners/reset_registration_token`
We plan to implement a new method to bind runners to a GitLab instance
as part of the new [GitLab Runner token architecture](https://docs.gitlab.com/ci/runners/new_creation_workflow/).
The work is planned in [this epic](https://gitlab.com/groups/gitlab-org/-/epics/7633).
This new architecture introduces a new method for registering runners and will eliminate the legacy
[runner registration token](https://docs.gitlab.com/security/tokens/#runner-registration-tokens-deprecated).
From GitLab 18.0 and later, the runner registration methods implemented by the new GitLab Runner token architecture will be the only supported methods.
</div>
<div class="deprecation breaking-change" data-milestone="18.0">
### Support for SUSE Linux Enterprise Server 15 SP2
<div class="deprecation-notes">
@ -2248,22 +2287,6 @@ and will be moved to the JiHu GitLab codebase.
<div class="deprecation breaking-change" data-milestone="18.0">
### `GITLAB_SHARED_RUNNERS_REGISTRATION_TOKEN` is deprecated
<div class="deprecation-notes">
- Announced in GitLab <span class="milestone">16.11</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/gitlab-org/gitlab/-/issues/453949).
</div>
The [`GITLAB_SHARED_RUNNERS_REGISTRATION_TOKEN`](https://docs.gitlab.com/administration/environment_variables/#supported-environment-variables) environment variable is deprecated. GitLab introduced a new [GitLab Runner token architecture](https://docs.gitlab.com/architecture/blueprints/runner_tokens/) in GitLab 15.8, which introduces a new method for registering runners and eliminates the legacy runner registration token. Please refer to the [documentation](https://docs.gitlab.com/ci/runners/new_creation_workflow/) for guidance on migrating to the new workflow.
</div>
<div class="deprecation breaking-change" data-milestone="18.0">
### `RemoteDevelopmentAgentConfig` GraphQL type is deprecated
<div class="deprecation-notes">
@ -2428,28 +2451,6 @@ determine the position of the merge request on the merge train use the
`index` field in `MergeTrainCar` instead. To get the count of MRs in a merge train,
use `count` from `cars` in `MergeTrains::TrainType` instead.
</div>
<div class="deprecation breaking-change" data-milestone="18.0">
### `runnerRegistrationToken` parameter for GitLab Runner Helm Chart
<div class="deprecation-notes">
- Announced in GitLab <span class="milestone">15.6</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/gitlab-org/gitlab/-/issues/381111).
</div>
The [`runnerRegistrationToken`](https://docs.gitlab.com/runner/install/kubernetes/) parameter to use the GitLab Helm Chart to install a runner on Kubernetes is deprecated.
We plan to implement a new method to bind runners to a GitLab instance leveraging `runnerToken`
as part of the new [GitLab Runner token architecture](https://docs.gitlab.com/ci/runners/new_creation_workflow/).
The work is planned in [this epic](https://gitlab.com/groups/gitlab-org/-/epics/7633).
From GitLab 18.0 and later, the methods to register runners introduced by the new GitLab Runner token architecture will be the only supported methods.
</div>
</div>

View File

@ -73,7 +73,10 @@ following when implementing a merge request approval policy:
manual jobs are run, the policy re-evaluates the merge request's jobs.
- For a merge request approval policy that evaluates the results of security scanners, all specified
scanners must have output a security report. If not, approvals are enforced to minimize the risk
of vulnerabilities being introduced.
of vulnerabilities being introduced. This behavior can affect:
- New projects where security scans are not yet established.
- Branches created before the security scans were configured.
- Projects with inconsistent scanner configurations between branches.
- The pipeline must produce artifacts for all enabled scanners, for both the source and target
branches. If not, there's no basis for comparison and so the policy can't be evaluated. You should
use a scan execution policy to enforce this requirement.
@ -83,6 +86,38 @@ following when implementing a merge request approval policy:
the policy is enforced. If not, the merge request approval policy cannot be evaluated and the
corresponding approvals are required.
## Best practices for using security scanners with merge request approval policies
When you create a new project, you can enforce both merge request approval policies and security scans on that project. However, incorrectly configured security scanners can affect the merge request approval policies.
There are multiple ways to configure security scans in new projects:
- In the project's CI/CD configuration by adding the scanners to the initial `.gitlab-ci.yml` configuration file.
- In a scan execution policy to enforce that pipelines run specific security scanners.
- In a pipeline execution policy to control which jobs must run in pipelines.
For simple use cases, you can use the project's CI/CD configuration. For a comprehensive security strategy, consider combining merge request approval policies with the other policy types.
To minimize unnecessary approval requirements and ensure accurate security evaluations:
- **Run security scans on your default branch first**: Before creating feature branches, ensure security scans have run successfully on your default branch.
- **Use consistent scanner configuration**: Run the same scanners in both source and target branches, preferably in a single pipeline.
- **Verify that scans produce artifacts**: Ensure that scans complete successfully and produce artifacts for comparison.
- **Keep branches synchronized**: Regularly merge changes from the default branch into feature branches.
- **Consider pipeline configurations**: For new projects, include security scanners in your initial `.gitlab-ci.yml` configuration.
### Verify security scanners before you apply merge request approval policies
By implementing your security scans in your new project before you apply a merge request approval policy, you can ensure security scanners run consistently before relying on merge request approval policies, which helps avoid situations where merge requests are blocked due to missing security scans.
To create and verify your security scanners and merge request approval policies together, use this recommended workflow:
1. Create the project.
1. Configure security scanners using the `.gitlab-ci.yml` configuration, a scan execution policy, or a pipeline execution policy.
1. Wait for the initial pipeline to complete on the default branch. Resolve any issues and rerun the pipeline to ensure it completes successfully before you continue.
1. Create merge requests using feature branches with the same security scanners configured. Again, ensure that the security scanners complete sucessfully.
1. Apply your merge request approval policies.
## Merge request with multiple pipelines
{{< history >}}
@ -744,6 +779,27 @@ To resolve these issues:
- Consider using [`fallback_behavior`](#fallback_behavior) with `open` to prevent invalid or unenforceable rules in a policy from requiring approval.
- Consider using the [`policy tuning`](#policy_tuning) setting `unblock_rules_using_execution_policies` to address scenarios where security scan artifacts are missing, and scan execution policies are enforced. When enabled, this setting makes approval rules optional when scan artifacts are missing from the target branch and a scan is required by a scan execution policy. This feature only works with an existing scan execution policy that has matching scanners. It offers flexibility in the merge request process when certain security scans cannot be performed due to missing artifacts.
### `Target: none` in security bot comments
If you see `Target: none` in security bot comments, it means GitLab couldn't find a security report for the target branch. To resolve this:
1. Run a pipeline on the target branch that includes the required security scanners.
1. Ensure the pipeline completes successfully and produces security reports.
1. Re-run the pipeline on the source branch. Creating a new commit also triggers the pipeline to re-run
#### Security bot messages
When the target branch has no security scans:
- The security bot may list all vulnerabilities found in the source branch.
- Some of the vulnerabilities might already exist in the target branch, but without a target branch scan, GitLab cannot determine which ones are new.
Potential solutions:
1. **Manual approvals**: Temporarily approve merge requests manually for new projects until security scans are established.
1. **Targeted policies**: Create separate policies for new projects with different approval requirements.
1. **Fallback behavior**: Consider using `fail: open` for policies on new projects, but be aware this may allow users to merge vulnerabilities even if scans fail.
### Support request for debugging of merge request approval policy
GitLab.com users may submit a [support ticket](https://about.gitlab.com/support/) titled "Merge request approval policy debugging". Provide the following details:

View File

@ -127,7 +127,7 @@ To improve your security, try these features:
| [Refactor Code](../gitlab_duo_chat/examples.md#refactor-code-in-the-ide) | Premium, Ultimate | GitLab Duo Pro or Enterprise | GitLab.com, GitLab Self-Managed, GitLab Dedicated | General availability |
| [Fix Code](../gitlab_duo_chat/examples.md#fix-code-in-the-ide) | Premium, Ultimate | GitLab Duo Pro or Enterprise | GitLab.com, GitLab Self-Managed, GitLab Dedicated | General availability |
| [GitLab Duo for the CLI](../../editor_extensions/gitlab_cli/_index.md#gitlab-duo-for-the-cli) | Ultimate | GitLab Duo Enterprise | GitLab.com, GitLab Self-Managed, GitLab Dedicated | General availability |
| [Merge Request Summary](../project/merge_requests/duo_in_merge_requests.md#generate-a-description-by-summarizing-code-changes) | Ultimate | GitLab Duo Enterprise | GitLab.com | Beta |
| [Merge Request Summary](../project/merge_requests/duo_in_merge_requests.md#generate-a-description-by-summarizing-code-changes) | Ultimate | GitLab Duo Enterprise | GitLab.com, GitLab Self-Managed | Beta |
| [Code Review](../project/merge_requests/duo_in_merge_requests.md#have-gitlab-duo-review-your-code) | Ultimate | GitLab Duo Enterprise | GitLab.com, GitLab Self-Managed, GitLab Dedicated | Beta |
| [Code Review Summary](../project/merge_requests/duo_in_merge_requests.md#summarize-a-code-review) | Ultimate | GitLab Duo Enterprise | GitLab.com, GitLab Self-Managed | Experiment |
| [Merge Commit Message Generation](../project/merge_requests/duo_in_merge_requests.md#generate-a-merge-commit-message) | Ultimate | GitLab Duo Enterprise | GitLab.com, GitLab Self-Managed, GitLab Dedicated | General availability |

View File

@ -14,7 +14,7 @@ title: SAML Group Sync
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/363084) for GitLab Self-Managed instances in GitLab 15.1.
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/363084) to GitLab Self-Managed in GitLab 15.1.
{{< /history >}}
@ -28,10 +28,35 @@ or that all groups are removed from GitLab to disable Group Sync.
{{< /alert >}}
SAML group sync allows users to be assigned to pre-existing GitLab groups with specific permissions based on the user's group assignment in the SAML identity provider (IdP). This feature allows you to create a many-to-many mapping between SAML IdP groups and GitLab groups. For example, if the user `@amelia` is assigned to the `security` group in the SAML IdP, SAML group sync allows you to assign `@amelia` to the `security-gitlab` and `vulnerability` GitLab groups with `maintainer` and `reporter` permissions, respectively. SAML group sync does not create groups. You [create groups separately](../_index.md#create-a-group), and then create the mapping.
Use SAML group sync to assign users with specific roles to existing GitLab groups,
based on the users' group assignment in the SAML identity provider (IdP).
With SAML group sync you can create a many-to-many mapping between SAML IdP groups and GitLab groups.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For a demo of Group Sync using Azure, see [Demo: SAML Group Sync](https://youtu.be/Iqvo2tJfXjg).
For example, if the user `@amelia` is assigned to the `security` group in the SAML IdP,
you can use SAML group sync to assign `@amelia` to the `security-gitlab` group with Maintainer role,
and to the `vulnerability` group with Reporter role.
SAML group sync does not create groups.
You have to first [create a group](../_index.md#create-a-group), then create the mapping.
## Role prioritization
Group sync determines the role and membership type of a user in the mapped group.
### Multiple SAML groups
If a user is a member of multiple SAML groups that map to the same GitLab group, the user is assigned the highest role from any of those SAML groups.
For example, if a user has the Guest role in a group and the Maintainer role in another group, they are assigned the Maintainer role.
### Membership types
If a user's role in a SAML group is higher than their role in one of its subgroups, their [membership](../../project/members/_index.md#display-direct-members) in the mapped GitLab group is different based on their assigned role in the mapped group.
If through group sync the user was assigned:
- A higher role, they are a direct member of the group.
- A role that is the same as or lower, they are an inherited member of the group.
## Configure SAML Group Links
@ -122,34 +147,6 @@ Now let's change the previous example so that the user is not a member of either
- When the user signs in to a group with `SAML1`, the user is given the `Owner` role in that group.
- When the user signs in with `SAML2`, the user is removed from the group because they are not a member of either configured group link.
### Role prioritization
#### Members of multiple mapped SAML groups
If a user is a member of multiple SAML groups mapped to the same GitLab group,
the user gets the highest role from the groups. For example, if one group
is linked as Guest and another Maintainer, a user in both groups gets the Maintainer
role.
#### Parent group role is higher than child group
Users granted:
- A higher role with Group Sync are displayed as having
[direct membership](../../project/members/_index.md#display-direct-members) of the group.
- A lower or the same role with Group Sync are displayed as having
[inherited membership](../../project/members/_index.md#membership-types) of the group.
### Use the API
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/290367) in GitLab 15.3.
{{< /history >}}
You can use the GitLab API to [list, add, and delete](../../../api/saml.md#saml-group-links) SAML group links.
## Configure SAML Group Sync
{{< alert type="note" >}}
@ -229,6 +226,9 @@ Microsoft has [announced](https://azure.microsoft.com/en-us/updates/azure-ad-is-
{{< /alert >}}
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For a demo of group sync using Microsoft Azure, see [Demo: SAML Group Sync](https://youtu.be/Iqvo2tJfXjg).
Azure AD sends up to 150 groups in the groups claim. When users are members of more than 150 groups Azure AD sends a
group overage claim attribute in the SAML response. Then group memberships must be obtained using the Microsoft Graph API.

View File

@ -15,7 +15,7 @@ GitLab Duo is designed to provide contextually relevant information during the l
{{< details >}}
- Tier: Ultimate with GitLab Duo Enterprise - [Start a trial](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/?type=free-trial)
- Offering: GitLab.com
- Offering: GitLab.com, GitLab Self-Managed
- Status: Beta
- LLM: Anthropic [Claude 3.5 Sonnet](https://console.cloud.google.com/vertex-ai/publishers/anthropic/model-garden/claude-3-5-sonnet)
@ -26,6 +26,7 @@ GitLab Duo is designed to provide contextually relevant information during the l
- [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/10401) in GitLab 16.2 as an [experiment](../../../policy/development_stages_support.md#experiment).
- [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/429882) to beta in GitLab 16.10.
- Changed to require GitLab Duo add-on in GitLab 17.6 and later.
- Feature flag `add_ai_summary_for_new_mr` [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/186108) in GitLab 17.11.
{{< /history >}}

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
module Gitlab
module BackgroundMigration
class BackfillExternalGroupAuditEventDestinations < BatchedMigrationJob
# This batched background migration is EE-only,
# see ee/lib/ee/gitlab/background_migration/backfill_external_group_audit_event_destinations.rb for
# the actual migration code.
feature_category :audit_events
def perform; end
end
end
end
Gitlab::BackgroundMigration::BackfillExternalGroupAuditEventDestinations.prepend_mod

View File

@ -12,6 +12,12 @@ module Gitlab
UUID_V5_PATTERN = /\h{8}-\h{4}-5\h{3}-\h{4}-\h{12}/
class << self
def urn
uuid = Digest::UUID.uuid_v4
"urn:uuid:#{uuid}"
end
def v5(name, namespace_id: default_namespace_id)
Digest::UUID.uuid_v5(namespace_id, name)
end

View File

@ -8836,6 +8836,9 @@ msgstr ""
msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead. %{link_start}How do I configure authentication using the GitLab database? %{link_end}"
msgstr ""
msgid "Authenticate with Docker Hub"
msgstr ""
msgid "Authenticate with GitHub"
msgstr ""
@ -14569,6 +14572,12 @@ msgstr ""
msgid "ColorMode|Light"
msgstr ""
msgid "ColorPicker|Enter any hex color or choose one of the suggested colors below."
msgstr ""
msgid "ColorPicker|Enter any hex color."
msgstr ""
msgid "ColorWidget|An error occurred while updating color."
msgstr ""
@ -15039,6 +15048,9 @@ msgstr ""
msgid "ComplianceFrameworksReport|Compliance framework ID"
msgstr ""
msgid "ComplianceFrameworksReport|Controls"
msgstr ""
msgid "ComplianceFrameworksReport|Copy ID"
msgstr ""
@ -15075,6 +15087,9 @@ msgstr ""
msgid "ComplianceFrameworksReport|Remove as default framework"
msgstr ""
msgid "ComplianceFrameworksReport|Requirements"
msgstr ""
msgid "ComplianceFrameworksReport|Set as default framework"
msgstr ""
@ -21853,6 +21868,9 @@ msgstr ""
msgid "Do you want to remove this deploy key?"
msgstr ""
msgid "Docker Hub pull rate limits begin April 1, 2025 and might affect CI/CD pipelines that pull Docker images. To prevent pipeline failures, configure the GitLab Dependency Proxy to authenticate with Docker Hub."
msgstr ""
msgid "Dockerfile"
msgstr ""
@ -23226,12 +23244,6 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
msgid "Enter any color or choose one of the suggested colors below."
msgstr ""
msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
msgstr ""

View File

@ -147,7 +147,7 @@ function main {
[ -z "${SKIP_FAST}" ] && run_rspec_fast
[ -z "${SKIP_JEST}" ] && run_jest
[ -z "${SKIP_NON_FAST}" ] && run_rspec_non_fast
[ -z "${SKIP_FEATURE}" ] && run_rspec_feature
[ "${SKIP_FEATURE:-1}" -eq 0 ] && run_rspec_feature
# Convenience ENV vars to run focused sections, copy and paste as a prefix to script command, and remove the one(s) you want to run focused
# SKIP_RUBOCOP=1 SKIP_FP=1 SKIP_FAST=1 SKIP_JEST=1 SKIP_NON_FAST=1 SKIP_FEATURE=1

View File

@ -65,7 +65,7 @@ RSpec.describe 'Project > Settings > Packages and registries > Container registr
end
expect(page).to have_current_path(project_settings_packages_and_registries_path(project))
expect(find('.gl-alert-body')).to have_content('Cleanup policy successfully saved.')
expect(find_by_testid('registry-update-settings-alert')).to have_content('Cleanup policy successfully saved.')
end
it 'does not save cleanup policy submit form with invalid regex' do

View File

@ -81,4 +81,27 @@ describe('JobDropdownItem', () => {
});
});
});
describe('job status', () => {
it.each`
statusGroup | shouldHaveFailedClass
${'success'} | ${false}
${'failed'} | ${true}
`(
'when status is $statusGroup, failed class presence should be $shouldHaveFailedClass',
({ statusGroup, shouldHaveFailedClass }) => {
const failedJob = {
...mockJobInfo,
detailedStatus: {
...detailedStatus,
group: statusGroup,
},
};
createComponent({ props: { job: failedJob } });
expect(wrapper.classes().includes('ci-job-item-failed')).toBe(shouldHaveFailedClass);
},
);
});
});

View File

@ -176,4 +176,35 @@ describe('job group dropdown component', () => {
);
});
});
describe('job status', () => {
it.each`
statusGroup | shouldHaveFailedClass
${'success'} | ${false}
${'failed'} | ${true}
`(
'when status is $statusGroup, failed class presence should be $shouldHaveFailedClass',
({ statusGroup, shouldHaveFailedClass }) => {
const testGroup = {
...group,
status: {
...group.status,
group: statusGroup,
},
};
createComponent({
props: { group: testGroup },
mountFn: mount,
});
expect(
findDisclosureDropdown()
.find('button')
.attributes('class')
.includes('ci-job-item-failed'),
).toBe(shouldHaveFailedClass);
},
);
});
});

View File

@ -4,7 +4,6 @@ import { mountExtended } from 'helpers/vue_test_utils_helper';
import { stubComponent } from 'helpers/stub_component';
import waitForPromises from 'helpers/wait_for_promises';
import BlobButtonGroup from '~/repository/components/header_area/blob_button_group.vue';
import ForkSuggestionModal from '~/repository/components/header_area/fork_suggestion_modal.vue';
import UploadBlobModal from '~/repository/components/upload_blob_modal.vue';
import { blobControlsDataMock, refMock } from 'ee_else_ce_jest/repository/mock_data';
@ -57,7 +56,6 @@ describe('BlobButtonGroup component', () => {
const findReplaceItem = () => wrapper.findComponent(GlDisclosureDropdownItem);
const findUploadBlobModal = () => wrapper.findComponent(UploadBlobModal);
const findForkSuggestionModal = () => wrapper.findComponent(ForkSuggestionModal);
beforeEach(async () => {
await createComponent();
@ -104,21 +102,15 @@ describe('BlobButtonGroup component', () => {
expect(showUploadBlobModalMock).not.toHaveBeenCalled();
});
it('triggers ForkSuggestionModal from the replace item', async () => {
it('emits showForkSuggestion from the replace item', async () => {
findReplaceItem().vm.$emit('action');
await nextTick();
expect(findForkSuggestionModal().props('visible')).toBe(true);
expect(wrapper.emitted('showForkSuggestion')).toEqual([[]]);
});
});
});
it('renders ForkSuggestionModal', () => {
expect(findForkSuggestionModal().props()).toMatchObject({
forkPath: 'fork/view/path',
});
});
it('should not disable replace button', () => {
expect(findReplaceItem().props('item')).toMatchObject({
extraAttrs: { disabled: false },
@ -134,5 +126,6 @@ describe('BlobButtonGroup component', () => {
path: 'some/file.js',
replacePath: 'some/replace/file.js',
});
expect(wrapper.emitted('showForkSuggestion')).toBeUndefined();
});
});

View File

@ -5,6 +5,7 @@ import waitForPromises from 'helpers/wait_for_promises';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { useMockInternalEventsTracking } from 'helpers/tracking_internal_events_helper';
import { logError } from '~/lib/logger';
import { visitUrl } from '~/lib/utils/url_utility';
import * as Sentry from '~/sentry/sentry_browser_wrapper';
import { createAlert } from '~/alert';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@ -21,6 +22,7 @@ import applicationInfoQuery from '~/blob/queries/application_info.query.graphql'
import createRouter from '~/repository/router';
import { updateElementsVisibility } from '~/repository/utils/dom';
import OpenMrBadge from '~/repository/components/header_area/open_mr_badge.vue';
import ForkSuggestionModal from '~/repository/components/header_area/fork_suggestion_modal.vue';
import {
blobControlsDataMock,
refMock,
@ -34,6 +36,13 @@ jest.mock('~/behaviors/shortcuts/shortcuts_blob');
jest.mock('~/blob/blob_line_permalink_updater');
jest.mock('~/alert');
jest.mock('~/lib/logger');
jest.mock('~/lib/utils/url_utility', () => ({
...jest.requireActual('~/lib/utils/url_utility'),
visitUrl: jest.fn(),
}));
jest.mock('~/lib/utils/common_utils', () => ({
isLoggedIn: jest.fn().mockReturnValue(true),
}));
jest.mock('~/sentry/sentry_browser_wrapper');
describe('Blob controls component', () => {
@ -115,7 +124,7 @@ describe('Blob controls component', () => {
},
mixins: [{ data: () => ({ ref: refMock }) }, glFeatureFlagMixin()],
stubs: {
WebIdeLink: false,
WebIdeLink,
},
});
@ -127,6 +136,7 @@ describe('Blob controls component', () => {
const findBlameButton = () => wrapper.findByTestId('blame');
const findPermalinkButton = () => wrapper.findByTestId('permalink');
const findWebIdeLink = () => wrapper.findComponent(WebIdeLink);
const findForkSuggestionModal = () => wrapper.findComponent(ForkSuggestionModal);
const findOverflowMenu = () => wrapper.findComponent(OverflowMenu);
const { bindInternalEventDocument } = useMockInternalEventsTracking();
@ -297,8 +307,8 @@ describe('Blob controls component', () => {
it('renders the WebIdeLink component with the correct props', () => {
expect(findWebIdeLink().props()).toMatchObject({
showEditButton: false,
editUrl: 'edit/blob/path/file.js',
webIdeUrl: 'ide/blob/path/file.js',
editUrl: 'https://edit/blob/path/file.js',
webIdeUrl: 'https://ide/blob/path/file.js',
needsToFork: false,
needsToForkWithWebIde: false,
showPipelineEditorButton: true,
@ -334,6 +344,73 @@ describe('Blob controls component', () => {
expect(findWebIdeLink().exists()).toBe(false);
});
describe('when can modify blob', () => {
it('redirects to WebIDE to edit the file', async () => {
findWebIdeLink().vm.$emit('edit', 'ide');
await nextTick();
expect(visitUrl).toHaveBeenCalledWith('https://ide/blob/path/file.js');
expect(findForkSuggestionModal().props('visible')).toBe(false);
});
it('redirects to single file editor to edit the file', async () => {
findWebIdeLink().vm.$emit('edit', 'simple');
await nextTick();
expect(visitUrl).toHaveBeenCalledWith('https://edit/blob/path/file.js');
expect(findForkSuggestionModal().props('visible')).toBe(false);
});
});
describe('when user cannot modify blob', () => {
it('changes ForkSuggestionModal visibility', async () => {
const blobControlsForForkResolver = jest.fn().mockResolvedValue({
data: {
project: {
...blobControlsDataMock,
userPermissions: {
...blobControlsDataMock.userPermissions,
pushCode: false,
createMergeRequestIn: true,
},
repository: {
...blobControlsDataMock.repository,
blobs: {
...blobControlsDataMock.repository.blobs,
nodes: [
{
...blobControlsDataMock.repository.blobs.nodes[0],
canModifyBlob: false,
canModifyBlobWithWebIde: false,
},
],
},
},
},
},
});
await createComponent({
blobControlsResolver: blobControlsForForkResolver,
glFeatures: { blobOverflowMenu: true },
});
findWebIdeLink().vm.$emit('edit', 'simple');
await nextTick();
expect(findForkSuggestionModal().props('visible')).toBe(true);
});
});
});
describe('ForkSuggestionModal component', () => {
it('renders ForkSuggestionModal', () => {
expect(findForkSuggestionModal().exists()).toBe(true);
expect(findForkSuggestionModal().props()).toMatchObject({
visible: false,
forkPath: 'fork/view/path',
});
});
});
describe('BlobOverflow dropdown', () => {
@ -370,6 +447,13 @@ describe('Blob controls component', () => {
expect(navigator.clipboard.writeText).toHaveBeenCalledWith('Example raw text content');
});
it('changes ForkSuggestionModal visibility when receives showForkSuggestion event', async () => {
findOverflowMenu().vm.$emit('showForkSuggestion');
await nextTick();
expect(findForkSuggestionModal().props('visible')).toBe(true);
});
});
});
});

View File

@ -5,7 +5,6 @@ import { mountExtended } from 'helpers/vue_test_utils_helper';
import { stubComponent } from 'helpers/stub_component';
import waitForPromises from 'helpers/wait_for_promises';
import BlobDeleteFileGroup from '~/repository/components/header_area/blob_delete_file_group.vue';
import ForkSuggestionModal from '~/repository/components/header_area/fork_suggestion_modal.vue';
import CommitChangesModal from '~/repository/components/commit_changes_modal.vue';
jest.mock('~/lib/utils/common_utils', () => ({
@ -56,7 +55,6 @@ describe('BlobDeleteFileGroup component', () => {
const findDeleteItem = () => wrapper.findComponent(GlDisclosureDropdownItem);
const findDeleteBlobModal = () => wrapper.findComponent(CommitChangesModal);
const findForkSuggestionModal = () => wrapper.findComponent(ForkSuggestionModal);
beforeEach(async () => {
await createComponent();
@ -105,21 +103,15 @@ describe('BlobDeleteFileGroup component', () => {
expect(showDeleteBlobModalMock).not.toHaveBeenCalled();
});
it('changes ForkSuggestionModal visibility', async () => {
it('emits showForkSuggestion event', async () => {
findDeleteItem().vm.$emit('action');
await nextTick();
expect(findForkSuggestionModal().props('visible')).toBe(true);
expect(wrapper.emitted('showForkSuggestion')).toEqual([[]]);
});
});
});
it('renders ForkSuggestionModal', () => {
expect(findForkSuggestionModal().props()).toMatchObject({
forkPath: 'fork/view/path',
});
});
it('renders DeleteBlobModal', () => {
expect(findDeleteBlobModal().props()).toMatchObject({
commitMessage: 'Delete file.js',
@ -133,5 +125,6 @@ describe('BlobDeleteFileGroup component', () => {
expect(findDeleteItem().props('item')).toMatchObject({
extraAttrs: { disabled: false },
});
expect(wrapper.emitted('showForkSuggestion')).toBeUndefined();
});
});

View File

@ -118,6 +118,16 @@ describe('Blob Overflow Menu', () => {
findBlobDefaultActionsGroup().vm.$emit('copy');
expect(wrapper.emitted('copy')).toBeUndefined();
});
it('proxy showForkSuggestion event from BlobButtonGRoup', () => {
findBlobButtonGroup().vm.$emit('showForkSuggestion');
expect(wrapper.emitted('showForkSuggestion')).toHaveLength(1);
});
it('proxy showForkSuggestion event from BlobDeleteFileGRoup', () => {
findBlobDeleteFileGroup().vm.$emit('showForkSuggestion');
expect(wrapper.emitted('showForkSuggestion')).toHaveLength(1);
});
});
});

View File

@ -103,8 +103,8 @@ export const blobControlsDataMock = {
canModifyBlob: true,
canModifyBlobWithWebIde: true,
forkAndViewPath: 'fork/view/path',
editBlobPath: 'edit/blob/path/file.js',
ideEditPath: 'ide/blob/path/file.js',
editBlobPath: 'https://edit/blob/path/file.js',
ideEditPath: 'https://ide/blob/path/file.js',
pipelineEditorPath: 'pipeline/editor/path/file.yml',
gitpodBlobUrl: 'gitpod/blob/url/file.js',
simpleViewer: {

View File

@ -4,6 +4,8 @@ import {
showSingleFileEditorForkSuggestion,
showWebIdeForkSuggestion,
showForkSuggestion,
isIdeTarget,
forkSuggestionForSelectedEditor,
} from '~/repository/utils/fork_suggestion_utils';
jest.mock('~/lib/utils/common_utils');
@ -103,4 +105,51 @@ describe('forkSuggestionUtils', () => {
).toBe(false);
});
});
describe('isIdeTarget', () => {
it('returns true when target is "ide"', () => {
expect(isIdeTarget('ide')).toBe(true);
});
it('returns false when target is not "ide"', () => {
expect(isIdeTarget('simple')).toBe(false);
expect(isIdeTarget('')).toBe(false);
expect(isIdeTarget(null)).toBe(false);
expect(isIdeTarget(undefined)).toBe(false);
});
});
describe('forkSuggestionForSelectedEditor', () => {
it('returns Web IDE fork suggestion when target is "ide"', () => {
const webIdeSuggestion = true;
const singleFileSuggestion = false;
expect(forkSuggestionForSelectedEditor('ide', webIdeSuggestion, singleFileSuggestion)).toBe(
webIdeSuggestion,
);
});
it('returns single file editor fork suggestion when target is not "ide"', () => {
const webIdeSuggestion = false;
const singleFileSuggestion = true;
expect(
forkSuggestionForSelectedEditor('simple', webIdeSuggestion, singleFileSuggestion),
).toBe(singleFileSuggestion);
});
it('handles different combinations of suggestion values', () => {
// Both true
expect(forkSuggestionForSelectedEditor('ide', true, true)).toBe(true);
expect(forkSuggestionForSelectedEditor('simple', true, true)).toBe(true);
// Both false
expect(forkSuggestionForSelectedEditor('ide', false, false)).toBe(false);
expect(forkSuggestionForSelectedEditor('simple', false, false)).toBe(false);
// Mixed values
expect(forkSuggestionForSelectedEditor('ide', true, false)).toBe(true);
expect(forkSuggestionForSelectedEditor('simple', false, true)).toBe(true);
});
});
});

View File

@ -15,7 +15,6 @@ import getTodosQuery from '~/todos/components/queries/get_todos.query.graphql';
import { INSTRUMENT_TAB_LABELS, STATUS_BY_TAB, TODO_WAIT_BEFORE_RELOAD } from '~/todos/constants';
import { mockTracking, unmockTracking } from 'jest/__helpers__/tracking_helper';
import getPendingTodosCount from '~/todos/components/queries/get_pending_todos_count.query.graphql';
import { userCounts } from '~/super_sidebar/user_counts_manager';
import {
todosResponse,
todosResponseEmptyLastPage,
@ -202,18 +201,15 @@ describe('TodosApp', () => {
});
it('shows the pending todos count once it has been fetched', async () => {
const previousCount = 5;
const updatedCount = getPendingTodosCountResponse.data.currentUser.todos.count;
Object.assign(userCounts, { todos: previousCount });
expect(previousCount).not.toBe(updatedCount);
createComponent();
expect(findPendingTodosCount().text()).toBe(`${previousCount}`);
expect(findPendingTodosCount().text()).toBe('-');
await waitForPromises();
expect(findPendingTodosCount().text()).toBe(`${updatedCount}`);
expect(findPendingTodosCount().text()).toBe(
String(getPendingTodosCountResponse.data.currentUser.todos.count),
);
});
it('refetches todos when page becomes visible again', async () => {

View File

@ -126,13 +126,15 @@ describe('ColorPicker', () => {
gon.suggested_label_colors = {};
createComponent(shallowMount);
expect(description()).toBe('Enter any color.');
expect(description()).toBe('Enter any hex color.');
expect(presetColors().exists()).toBe(false);
});
it('shows the suggested colors', () => {
createComponent(shallowMount);
expect(description()).toBe('Enter any color or choose one of the suggested colors below.');
expect(description()).toBe(
'Enter any hex color or choose one of the suggested colors below.',
);
expect(presetColors()).toHaveLength(4);
});
@ -150,7 +152,9 @@ describe('ColorPicker', () => {
};
createComponent(shallowMount, { suggestedColors: customColors });
expect(description()).toBe('Enter any color or choose one of the suggested colors below.');
expect(description()).toBe(
'Enter any hex color or choose one of the suggested colors below.',
);
expect(presetColors()).toHaveLength(2);
expect(presetColors().at(0).attributes('title')).toBe('Red');
expect(presetColors().at(1).attributes('title')).toBe('Gray');

View File

@ -5,6 +5,14 @@ require 'spec_helper'
RSpec.describe Gitlab::UUID do
let_it_be(:name) { "GitLab" }
describe '.urn' do
subject(:urn) { described_class.urn }
it 'outputs RFC 4122 conformant URN' do
expect(urn).to match(/^urn:uuid:\h{8}-\h{4}-\h{4}-\h{4}-\h{12}$/)
end
end
describe '.v5' do
subject { described_class.v5(name) }

View File

@ -0,0 +1,122 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe EnsureRunnerTaggingsExist, feature_category: :runner, migration: :gitlab_ci do
let(:runners_table) { table(:ci_runners, database: :ci, primary_key: :id) }
let(:runner_taggings_table) { table(:ci_runner_taggings, database: :ci, primary_key: :id) }
let(:taggings_table) { table(:taggings, database: :ci) }
let(:tags_table) { table(:tags, database: :ci) }
let(:instance_runner) { runners_table.create!(runner_type: 1) }
let(:group_runner) { runners_table.create!(runner_type: 2, sharding_key_id: 10) }
let(:project_runner) { runners_table.create!(runner_type: 3, sharding_key_id: 11) }
let(:tag1) { tags_table.create!(name: 'docker') }
let(:tag2) { tags_table.create!(name: 'postgres') }
let(:tag3) { tags_table.create!(name: 'ruby') }
let(:tag4) { tags_table.create!(name: 'golang') }
let(:connection) { Ci::ApplicationRecord.connection }
before do
taggings_table.create!(tag_id: tag1.id, taggable_id: instance_runner.id,
taggable_type: 'Ci::Runner', context: :tags)
taggings_table.create!(tag_id: tag2.id, taggable_id: instance_runner.id,
taggable_type: 'Ci::Runner', context: :tags)
taggings_table.create!(tag_id: tag3.id, taggable_id: instance_runner.id,
taggable_type: 'Ci::Runner', context: :tags)
taggings_table.create!(tag_id: tag1.id, taggable_id: group_runner.id,
taggable_type: 'Ci::Runner', context: :tags)
taggings_table.create!(tag_id: tag2.id, taggable_id: group_runner.id,
taggable_type: 'Ci::Runner', context: :tags)
taggings_table.create!(tag_id: tag3.id, taggable_id: project_runner.id,
taggable_type: 'Ci::Runner', context: :tags)
taggings_table.create!(tag_id: tag4.id, taggable_id: project_runner.id,
taggable_type: 'Ci::Runner', context: :tags)
taggings_table.create!(tag_id: tag3.id, taggable_id: non_existing_record_id,
taggable_type: 'Ci::Runner', context: :tags)
taggings_table.create!(tag_id: tag3.id, taggable_id: project_runner.id,
taggable_type: 'CommitStatus', context: :tags)
end
describe '#up' do
it 'copies records over into ci_runner_taggings' do
expect { migrate! }
.to change { runner_taggings_table.count }
.from(0)
.to(7)
expect(tag_ids_from_taggings_for(instance_runner))
.to match_array(runner_taggings_for(instance_runner).pluck(:tag_id))
expect(tag_ids_from_taggings_for(group_runner))
.to match_array(runner_taggings_for(group_runner).pluck(:tag_id))
expect(tag_ids_from_taggings_for(project_runner))
.to match_array(runner_taggings_for(project_runner).pluck(:tag_id))
expect(runner_taggings_for(instance_runner).pluck(:sharding_key_id).uniq)
.to contain_exactly(nil)
expect(runner_taggings_for(group_runner).pluck(:sharding_key_id).uniq)
.to contain_exactly(10)
expect(runner_taggings_for(project_runner).pluck(:sharding_key_id).uniq)
.to contain_exactly(11)
expect(runner_taggings_for(non_existing_record_id)).to be_empty
end
context 'when the table is already renamed' do
before do
connection.execute(<<~SQL.squish)
ALTER TABLE ci_runners RENAME TO _test_runners_copy;
ALTER TABLE ci_runners_e59bb2812d RENAME TO ci_runners;
SQL
end
after do
connection.execute(<<~SQL.squish)
ALTER TABLE ci_runners RENAME TO ci_runners_e59bb2812d;
ALTER TABLE _test_runners_copy RENAME TO ci_runners;
SQL
end
it 'copies records over into ci_runner_taggings' do
expect { migrate! }
.to change { runner_taggings_table.count }
.from(0)
.to(7)
end
end
context 'when records already exist in ci_runner_taggings' do
before do
runner_taggings_table.create!(
runner_id: instance_runner.id,
tag_id: tag1.id,
runner_type: 1
)
end
it 'does not copy records over into ci_runner_taggings' do
expect { migrate! }
.not_to change { runner_taggings_table.count }
.from(1)
end
end
def tag_ids_from_taggings_for(runner)
taggings_table
.where(taggable_id: runner, taggable_type: 'Ci::Runner')
.pluck(:tag_id)
end
def runner_taggings_for(runner)
runner_taggings_table.where(runner_id: runner)
end
end
end

View File

@ -0,0 +1,38 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe QueueBackfillExternalGroupAuditEventDestinations,
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_external_audit_event_destinations,
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

@ -0,0 +1,60 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe QueueUpdatePackageNameInPmAffectedPackages, feature_category: :dependency_management do
let(:pm_advisories) { table(:pm_advisories) }
let(:pm_affected_packages) { table(:pm_affected_packages) }
let(:advisory_1) do
pm_advisories.create!(advisory_xid: 'xid', source_xid: 'xid', identifiers: [], published_date: Date.current)
end
let(:affected_package_1) do
pm_affected_packages.create!(pm_advisory_id: advisory_1.id, purl_type: 8, package_name: 'Django',
affected_range: '>1')
end
let(:affected_package_2) do
pm_affected_packages.create!(pm_advisory_id: advisory_1.id, purl_type: 6, package_name: 'Django',
affected_range: '>1')
end
let(:affected_package_3) do
pm_affected_packages.create!(pm_advisory_id: advisory_1.id, purl_type: 8, package_name: 'accesscontrol',
affected_range: '>1')
end
let!(:affected_packages) { [affected_package_1, affected_package_2, affected_package_3] }
describe '#up' do
subject(:migration) do
described_class.new
end
it 'updates package_name with its normalized value' do
migration.up
expect(affected_package_1.reload.package_name).to eq('django')
end
it 'does not update those records with a different purl_type' do
expect { migration.up }.not_to change { affected_package_2.reload.package_name }
end
it 'does not update those records that does not match the regex' do
expect { migration.up }.not_to change { affected_package_3.reload.package_name }
end
context 'with existing record matching (pm_advisory_id, purl_type, package_name, distro_version)' do
before do
pm_affected_packages.create!(pm_advisory_id: advisory_1.id, purl_type: 8, package_name: 'django',
affected_range: '>1')
end
it 'does not update the record that could violate DB constraint' do
expect { migration.up }.not_to change { affected_package_1.reload.package_name }
end
end
end
end

View File

@ -34,7 +34,7 @@ These permissions are applied to the CI/CD job tokens in a specified project.
This feature is an [experiment](../../policy/development_stages_support.md#experiment) and subject to change without notice. This feature is not ready for production use. If you want to use this feature, you should test outside of production first.
## Enable fine-grained permissions for projects
## Enable use of fine-grained permissions
Prerequisites:
@ -50,6 +50,32 @@ To enable fine-grained permissions for all projects in a group:
1. Expand **General pipelines**.
1. Turn on the **Enable fine-grained permissions for CI/CD job tokens** toggle.
## Add fine-grained permissions to the job token allowlist
Prerequisites:
- You must have at least the Maintainer role for the project.
- You must enable the use of fine-grained permissions for a project.
You can add fine-grained permissions to groups and projects on your job token allowlist. This allows
them to use job tokens to access specific project resources and more accurately control which
resources are available to these groups and projects.
To add fine-grained permissions to groups or projects on the job token allowlist:
1. On the left sidebar, select **Search or go to** and find your project.
1. Select **Settings > CI/CD**.
1. Expand **Job token permissions**.
1. In the **CI/CD job token allowlist** section, select **Add**.
1. From the dropdown list, select **Group or project**.
1. Enter the path to an existing group or project.
1. Select **Fine-grained permissions**.
1. Grant permissions to the [available API endpoints](#available-api-endpoints).
1. Select **Add**.
GitLab adds the group or project to the job token allowlist with the specified permissions. The group or project can now
access any allowed resources in the current project.
## Available API endpoints
The following endpoints are available for CI/CD job tokens.