Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-05-24 12:12:31 +00:00
parent 852aade153
commit 41bd3e161f
109 changed files with 891 additions and 513 deletions

View File

@ -596,13 +596,10 @@ lib/gitlab/checks/**
/doc/administration/redis/ @axil
/doc/administration/reference_architectures/ @axil
/doc/administration/reply_by_email_postfix_setup.md @axil
/doc/administration/reporting/ @phillipwells
/doc/administration/reporting/spamcheck.md @axil
/doc/administration/reporting/ @axil
/doc/administration/repository_checks.md @eread
/doc/administration/repository_storage_paths.md @eread
/doc/administration/restart_gitlab.md @axil
/doc/administration/review_abuse_reports.md @phillipwells
/doc/administration/review_spam_logs.md @phillipwells
/doc/administration/server_hooks.md @eread
/doc/administration/settings/account_and_limit_settings.md @msedlakjakubowski
/doc/administration/settings/continuous_integration.md @marcel.amirault @lyspin
@ -621,6 +618,7 @@ lib/gitlab/checks/**
/doc/administration/settings/package_registry_rate_limits.md @phillipwells
/doc/administration/settings/project_integration_management.md @eread @ashrafkhamis
/doc/administration/settings/push_event_activities_limit.md @msedlakjakubowski
/doc/administration/settings/rate_limit_on_groups_api.md @lciutacu
/doc/administration/settings/rate_limit_on_issues_creation.md @msedlakjakubowski
/doc/administration/settings/rate_limit_on_members_api.md @lciutacu
/doc/administration/settings/rate_limit_on_notes_creation.md @msedlakjakubowski
@ -684,6 +682,8 @@ lib/gitlab/checks/**
/doc/api/geo_nodes.md @axil
/doc/api/geo_sites.md @axil
/doc/api/google_cloud_integration.md @jglassman1
/doc/api/graphql/audit_event_streaming_groups.md @eread
/doc/api/graphql/audit_event_streaming_instances.md @eread
/doc/api/graphql/audit_report.md @eread
/doc/api/graphql/branch_rules.md @msedlakjakubowski
/doc/api/graphql/custom_emoji.md @msedlakjakubowski
@ -875,12 +875,9 @@ lib/gitlab/checks/**
/doc/install/ @axil
/doc/integration/ @jglassman1
/doc/integration/advanced_search/ @ashrafkhamis
/doc/integration/akismet.md @phillipwells
/doc/integration/arkose.md @phillipwells
/doc/integration/datadog.md @fneill
/doc/integration/diffblue_cover.md @marcel.amirault @lyspin
/doc/integration/external-issue-tracker.md @eread @ashrafkhamis
/doc/integration/github.md @marcel.amirault @lyspin
/doc/integration/gitpod.md @ashrafkhamis
/doc/integration/gmail_action_buttons_for_gitlab.md @eread @ashrafkhamis
/doc/integration/index.md @eread @ashrafkhamis
@ -888,7 +885,6 @@ lib/gitlab/checks/**
/doc/integration/jira/ @eread @ashrafkhamis
/doc/integration/mattermost/ @axil
/doc/integration/partner_marketplace.md @fneill
/doc/integration/recaptcha.md @phillipwells
/doc/integration/sourcegraph.md @msedlakjakubowski
/doc/integration/trello_power_up.md @eread @ashrafkhamis
/doc/integration/vault.md @phillipwells
@ -898,8 +894,6 @@ lib/gitlab/checks/**
/doc/raketasks/spdx.md @rdickenson
/doc/raketasks/x509_signatures.md @msedlakjakubowski
/doc/security/ @jglassman1
/doc/security/email_verification.md @phillipwells
/doc/security/identity_verification.md @phillipwells
/doc/solutions/ @jfullam @brianwald @Darwinjs
/doc/subscriptions/ @fneill
/doc/subscriptions/gitlab_dedicated/ @lyspin
@ -941,9 +935,10 @@ lib/gitlab/checks/**
/doc/user/application_security/ @rdickenson
/doc/user/asciidoc.md @msedlakjakubowski
/doc/user/clusters/ @phillipwells
/doc/user/compliance/ @rdickenson
/doc/user/compliance/compliance_center/ @eread
/doc/user/compliance/index.md @eread
/doc/user/compliance/ @eread
/doc/user/compliance/license_approval_policies.md @rdickenson
/doc/user/compliance/license_list.md @rdickenson
/doc/user/compliance/license_scanning_of_cyclonedx_files/ @rdickenson
/doc/user/custom_roles.md @jglassman1
/doc/user/custom_roles/ @jglassman1
/doc/user/discussions/ @aqualls
@ -971,9 +966,7 @@ lib/gitlab/checks/**
/doc/user/group/issues_analytics/ @lciutacu
/doc/user/group/iterations/ @msedlakjakubowski
/doc/user/group/manage.md @lciutacu
/doc/user/group/moderate_users.md @phillipwells
/doc/user/group/planning_hierarchy/ @msedlakjakubowski
/doc/user/group/reporting/ @phillipwells
/doc/user/group/repositories_analytics/ @marcel.amirault @lyspin
/doc/user/group/roadmap/ @msedlakjakubowski
/doc/user/group/saml_sso/ @jglassman1
@ -1054,7 +1047,6 @@ lib/gitlab/checks/**
/doc/user/project/web_ide/ @ashrafkhamis
/doc/user/project/working_with_projects.md @lciutacu
/doc/user/public_access.md @lciutacu
/doc/user/report_abuse.md @phillipwells
/doc/user/reserved_names.md @lciutacu
/doc/user/search/ @ashrafkhamis
/doc/user/search/command_palette.md @sselhorn

View File

@ -18,23 +18,6 @@ Layout/ArgumentAlignment:
- 'app/graphql/mutations/work_items/delete.rb'
- 'app/graphql/mutations/work_items/update.rb'
- 'app/graphql/resolvers/admin/analytics/usage_trends/measurements_resolver.rb'
- 'ee/app/graphql/ee/mutations/issues/create.rb'
- 'ee/app/graphql/ee/mutations/issues/update.rb'
- 'ee/app/graphql/ee/mutations/work_items/create.rb'
- 'ee/app/graphql/ee/mutations/work_items/update.rb'
- 'ee/app/graphql/ee/resolvers/issues/base_parent_resolver.rb'
- 'ee/app/graphql/ee/resolvers/issues/base_resolver.rb'
- 'ee/app/graphql/ee/resolvers/namespace_projects_resolver.rb'
- 'ee/app/graphql/ee/resolvers/work_items_resolver.rb'
- 'ee/app/graphql/ee/types/alert_management/http_integration_type.rb'
- 'ee/app/graphql/ee/types/boards/board_issue_input_base_type.rb'
- 'ee/app/graphql/ee/types/boards/board_issue_input_type.rb'
- 'ee/app/graphql/ee/types/boards/negated_board_issue_input_type.rb'
- 'ee/app/graphql/ee/types/branch_protections/base_access_level_type.rb'
- 'ee/app/graphql/ee/types/branch_rules/branch_protection_type.rb'
- 'ee/app/graphql/ee/types/ci/runner_countable_connection_type.rb'
- 'ee/app/graphql/ee/types/deployment_type.rb'
- 'ee/app/graphql/ee/types/environment_type.rb'
- 'ee/app/graphql/mutations/iterations/cadences/destroy.rb'
- 'ee/app/graphql/mutations/iterations/create.rb'
- 'ee/app/graphql/mutations/iterations/update.rb'

View File

@ -20,22 +20,6 @@ Layout/SpaceInLambdaLiteral:
- 'app/models/namespace_statistics.rb'
- 'app/models/note.rb'
- 'app/models/note_diff_file.rb'
- 'app/models/operations/feature_flags/user_list.rb'
- 'app/models/packages/build_info.rb'
- 'app/models/packages/maven/metadatum.rb'
- 'app/models/packages/package.rb'
- 'app/models/packages/tag.rb'
- 'app/models/personal_access_token.rb'
- 'app/models/project.rb'
- 'app/models/project_daily_statistic.rb'
- 'app/models/project_feature_usage.rb'
- 'app/models/project_group_link.rb'
- 'app/models/project_statistics.rb'
- 'app/models/projects/import_export/relation_export.rb'
- 'app/models/projects/topic.rb'
- 'app/models/prometheus_alert.rb'
- 'app/models/prometheus_alert_event.rb'
- 'app/models/prometheus_metric.rb'
- 'app/serializers/analytics/cycle_analytics/stage_entity.rb'
- 'app/serializers/base_discussion_entity.rb'
- 'app/serializers/blob_entity.rb'
@ -79,28 +63,6 @@ Layout/SpaceInLambdaLiteral:
- 'ee/app/models/concerns/ee/protected_ref.rb'
- 'ee/app/models/concerns/filterable_by_test_reports.rb'
- 'ee/app/models/concerns/issue_widgets/acts_like_requirement.rb'
- 'ee/app/models/saml_group_link.rb'
- 'ee/app/models/sca/license_compliance.rb'
- 'ee/app/models/security/finding.rb'
- 'ee/app/models/security/orchestration_policy_configuration.rb'
- 'ee/app/models/security/scan.rb'
- 'ee/app/models/security/training.rb'
- 'ee/app/models/security/training_provider.rb'
- 'ee/app/models/software_license.rb'
- 'ee/app/models/software_license_policy.rb'
- 'ee/app/models/vulnerabilities/external_issue_link.rb'
- 'ee/app/models/vulnerabilities/feedback.rb'
- 'ee/app/models/vulnerabilities/finding.rb'
- 'ee/app/models/vulnerabilities/finding_link.rb'
- 'ee/app/models/vulnerabilities/finding_remediation.rb'
- 'ee/app/models/vulnerabilities/finding_signature.rb'
- 'ee/app/models/vulnerabilities/historical_statistic.rb'
- 'ee/app/models/vulnerabilities/identifier.rb'
- 'ee/app/models/vulnerabilities/issue_link.rb'
- 'ee/app/models/vulnerabilities/read.rb'
- 'ee/app/models/vulnerabilities/remediation.rb'
- 'ee/app/models/vulnerabilities/scanner.rb'
- 'ee/app/models/vulnerabilities/statistic.rb'
- 'ee/app/serializers/blocking_merge_request_entity.rb'
- 'ee/app/serializers/clusters/environment_entity.rb'
- 'ee/app/serializers/dashboard_operations_project_entity.rb'

View File

@ -40,6 +40,7 @@ RSpec/FilePath:
- 'spec/requests/api/issues/get_project_issues_spec.rb'
- 'spec/requests/api/issues/issues_spec.rb'
- 'spec/requests/api/issues/post_projects_issues_spec.rb'
- 'ee/spec/requests/api/ee/issues/post_projects_issues_spec.rb'
- 'spec/requests/api/issues/put_projects_issues_spec.rb'
- 'spec/requests/api/pages/pages_spec.rb'
- 'spec/services/ci/create_pipeline_service/*'

View File

@ -1 +1 @@
v17.1.0-rc3
v17.1.0-rc5

View File

@ -273,7 +273,7 @@ gem 're2', '2.7.0' # rubocop:todo Gemfile/MissingFeatureCategory
# Misc
gem 'semver_dialects', '~> 2.0', '>= 2.0.2', feature_category: :static_application_security_testing
gem 'semver_dialects', '~> 2.0', '>= 2.0.2', feature_category: :software_composition_analysis
gem 'version_sorter', '~> 2.3' # rubocop:todo Gemfile/MissingFeatureCategory
gem 'csv_builder', path: 'gems/csv_builder' # rubocop:todo Gemfile/MissingFeatureCategory

View File

@ -551,7 +551,7 @@
{"name":"redcarpet","version":"3.6.0","platform":"ruby","checksum":"8ad1889c0355ff4c47174af14edd06d62f45a326da1da6e8a121d59bdcd2e9e9"},
{"name":"redis","version":"5.2.0","platform":"ruby","checksum":"336b975a56b166c6af4d4a1026c71dbed429ba5dc949aac373ef2fded07936b4"},
{"name":"redis-actionpack","version":"5.4.0","platform":"ruby","checksum":"f10cf649ab05914716d63334d7f709221ecc883b87cf348f90ecfe0c35ea3540"},
{"name":"redis-client","version":"0.22.1","platform":"ruby","checksum":"b411b3812e83f817069dc20651dd3b01d4d417a0cab0f04fbaf143d6de19107e"},
{"name":"redis-client","version":"0.22.2","platform":"ruby","checksum":"31fee4b7cf04109b227327fabeaaf1fc5b652cf48a186a03bc607e40767bacc0"},
{"name":"redis-cluster-client","version":"0.8.2","platform":"ruby","checksum":"1ced1b8a86e2bd57d297de35194e06f84da306f22c13cfbb7103e6458055eb80"},
{"name":"redis-clustering","version":"5.2.0","platform":"ruby","checksum":"685f388e0bdd81091a96cce9a46e22e727213d5fa14ebfc5111e110440e0038e"},
{"name":"redis-namespace","version":"1.11.0","platform":"ruby","checksum":"e91a1aa2b2d888b6dea1d4ab8d39e1ae6fac3426161feb9d91dd5cca598a2239"},

View File

@ -1484,7 +1484,7 @@ GEM
actionpack (>= 5, < 8)
redis-rack (>= 2.1.0, < 4)
redis-store (>= 1.1.0, < 2)
redis-client (0.22.1)
redis-client (0.22.2)
connection_pool
redis-cluster-client (0.8.2)
redis-client (~> 0.22)

View File

@ -105,7 +105,7 @@ export default {
title: $options.i18n.moveCardText,
boundary: 'viewport',
}"
class="move-to-position gl-display-block gl-mb-2 gl-ml-auto -gl-mt-3 gl-mr-n3 js-no-trigger"
class="move-to-position gl-display-block gl-mb-2 gl-ml-auto -gl-mt-3 -gl-mr-3 js-no-trigger"
category="tertiary"
:items="$options.BOARD_CARD_MOVE_TO_POSITIONS_OPTIONS"
icon="ellipsis_v"

View File

@ -172,7 +172,7 @@ export default {
v-if="node.attrs.showPreview"
:contenteditable="false"
data-testid="sandbox-preview"
class="!-gl-mt-3 gl-ml-n4! gl-mr-n4! gl-mb-3 gl-bg-white! gl-p-4 gl-border-b-1 gl-border-b-solid gl-border-b-gray-100"
class="!-gl-mt-3 gl-ml-n4! !-gl-mr-4 gl-mb-3 gl-bg-white! gl-p-4 gl-border-b-1 gl-border-b-solid gl-border-b-gray-100"
>
<sandboxed-mermaid v-if="node.attrs.language === 'mermaid'" :source="diagramSource" />
<img v-else ref="diagramContainer" :src="diagramUrl" />
@ -191,7 +191,7 @@ export default {
data-testid="code-suggestion-box"
>
<div
class="md-suggestion-header gl-flex-wrap gl-z-1 gl-w-full gl-border-none! gl-font-regular gl-px-4 gl-py-3 gl-border-b-1! gl-border-b-solid! gl-mr-n10!"
class="md-suggestion-header gl-flex-wrap gl-z-1 gl-w-full gl-border-none! gl-font-regular gl-px-4 gl-py-3 gl-border-b-1! gl-border-b-solid!"
>
<div class="gl-font-weight-bold gl-pr-3">
{{ __('Suggested change') }}

View File

@ -309,7 +309,7 @@ export default {
<imported-badge v-if="isImported" :importable-type="$options.TYPE_COMMENT" size="sm" />
</span>
</div>
<div class="gl-display-flex gl-align-items-flex-start -gl-mt-2 gl-mr-n2">
<div class="gl-display-flex gl-align-items-flex-start -gl-mt-2 -gl-mr-2">
<slot name="resolve-discussion"></slot>
<emoji-picker
v-if="canAwardEmoji"

View File

@ -191,7 +191,7 @@ export default {
<div
class="item-attributes-area gl-display-flex gl-align-items-center gl-flex-wrap gl-gap-3"
>
<span v-if="hasPipeline" class="mr-ci-status order-md-last gl-md-ml-3 gl-mr-n2">
<span v-if="hasPipeline" class="mr-ci-status order-md-last gl-md-ml-3 -gl-mr-2">
<ci-icon :status="pipelineStatus" />
</span>

View File

@ -196,7 +196,7 @@ export default {
<span
v-if="isForked"
v-gl-tooltip
class="gl-align-middle gl-mr-n2"
class="gl-align-middle -gl-mr-2"
:title="__('The source project is a fork')"
>
<gl-icon name="fork" :size="12" class="gl-ml-1" />

View File

@ -2,6 +2,7 @@ import 'bootstrap/js/dist/collapse';
import MirrorRepos from '~/mirrors/mirror_repos';
import mountBranchRules from '~/projects/settings/repository/branch_rules/mount_branch_rules';
import mountDefaultBranchSelector from '~/projects/settings/mount_default_branch_selector';
import mountRepositoryMaintenance from '~/projects/settings/repository/maintenance/mount_repository_maintenance';
import initForm from '../form';
@ -12,3 +13,4 @@ if (mirrorReposContainer) new MirrorRepos(mirrorReposContainer).init();
mountBranchRules(document.getElementById('js-branch-rules'));
mountDefaultBranchSelector(document.querySelector('.js-select-default-branch'));
mountRepositoryMaintenance();

View File

@ -335,7 +335,7 @@ export default {
<div class="col-12">
<gl-form-group :label="$options.i18n.title.label" label-for="wiki_title">
<template v-if="!isTemplate" #description>
<gl-icon class="gl-mr-n1" name="bulb" />
<gl-icon class="-gl-mr-1" name="bulb" />
{{ titleHelpText }}
<gl-link :href="helpPath" target="_blank">
{{ $options.i18n.title.helpText.learnMore }}

View File

@ -0,0 +1,14 @@
import Vue from 'vue';
import RemoveBlobs from '~/projects/settings/repository/maintenance/remove_blobs.vue';
export default function mountRepositoryMaintenance() {
const removeBlobsEl = document.querySelector('.js-maintenance-remove-blobs');
if (!removeBlobsEl) return false;
return new Vue({
el: removeBlobsEl,
render(createElement) {
return createElement(RemoveBlobs);
},
});
}

View File

@ -0,0 +1,111 @@
<script>
import { GlButton, GlDrawer, GlLink, GlFormTextarea, GlModal } from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper';
import { DRAWER_Z_INDEX } from '~/lib/utils/constants';
import { getContentWrapperHeight } from '~/lib/utils/dom_utils';
import { s__ } from '~/locale';
const i18n = {
removeBlobs: s__('ProjectMaintenance|Remove blobs'),
description: s__(
'ProjectMaintenance|Enter a list of object IDs to be removed to reduce repository size.',
),
helpLink: s__('ProjectMaintenance|How do I get a list of object IDs?'),
label: s__('ProjectMaintenance|Blob IDs to remove'),
helpText: s__('ProjectMaintenance|Enter multiple entries on separate lines.'),
modalPrimaryText: s__('ProjectMaintenance|Yes, remove blobs'),
modalCancelText: s__('ProjectMaintenance|Cancel'),
modalContent: s__(
'ProjectMaintenance|Removing blobs by ID cannot be undone. Are you sure you want to continue?',
),
};
export default {
i18n,
DRAWER_Z_INDEX,
removeBlobsHelpLink: helpPagePath('/user/project/repository/reducing_the_repo_size_using_git'),
modalCancel: { text: i18n.modalCancelText },
modalPrimary: { text: i18n.modalPrimaryText, attributes: { variant: 'danger' } },
components: { GlButton, GlDrawer, GlLink, GlFormTextarea, GlModal },
data() {
return { isDrawerOpen: false, blobIDs: null, showConfirmationModal: false };
},
computed: {
getDrawerHeaderHeight() {
return getContentWrapperHeight();
},
},
methods: {
openDrawer() {
this.isDrawerOpen = true;
},
closeDrawer() {
this.blobIDs = null;
this.isDrawerOpen = false;
},
removeBlobs() {
this.showConfirmationModal = true;
},
removeBlobsConfirm() {
// TODO (follow-up MR): submit mutation + show alert/toast...
this.closeDrawer();
},
},
};
</script>
<template>
<div>
<gl-button class="gl-mb-6" data-testid="drawer-trigger" @click="openDrawer">{{
$options.i18n.removeBlobs
}}</gl-button>
<gl-drawer
:header-height="getDrawerHeaderHeight"
:open="isDrawerOpen"
:z-index="$options.DRAWER_Z_INDEX"
@close="closeDrawer"
>
<template #title>
<h4 class="gl-m-0">{{ $options.i18n.removeBlobs }}</h4>
</template>
<div>
<p class="gl-text-secondary">
{{ $options.i18n.description }}
<gl-link :href="$options.removeBlobsHelpLink" target="_blank">{{
$options.i18n.helpLink
}}</gl-link>
</p>
<label for="blobs">{{ $options.i18n.label }}</label>
<gl-form-textarea
id="blobs"
v-model.trim="blobIDs"
class="!gl-font-monospace gl-mb-3"
autofocus
/>
<p class="gl-text-gray-400">{{ $options.i18n.helpText }}</p>
<gl-button
data-testid="remove-blobs"
variant="danger"
:disabled="!blobIDs"
@click="removeBlobs"
>{{ $options.i18n.removeBlobs }}</gl-button
>
</div>
</gl-drawer>
<gl-modal
v-model="showConfirmationModal"
:title="$options.i18n.removeBlobs"
modal-id="remove-blobs-confirmation-modal"
:action-cancel="$options.modalCancel"
:action-primary="$options.modalPrimary"
@primary="removeBlobsConfirm"
>
{{ $options.i18n.modalContent }}
</gl-modal>
</div>
</template>

View File

@ -127,8 +127,8 @@ export default {
accessLevelTooltipDescription: s__(
'SecretDetection|Only a project maintainer or owner can toggle this feature.',
),
toastMessageEnabled: s__('SecretDetection|Pre-receive Secret Detection is enabled'),
toastMessageDisabled: s__('SecretDetection|Pre-receive Secret Detection is disabled'),
toastMessageEnabled: s__('SecretDetection|Secret push protection is enabled'),
toastMessageDisabled: s__('SecretDetection|Secret push protection is disabled'),
},
};
</script>
@ -188,7 +188,7 @@ export default {
class="gl-mt-5"
:disabled="isToggleDisabled"
:value="toggleValue"
:label="s__('SecurityConfiguration|Toggle Pre-receive secret detection')"
:label="s__('SecurityConfiguration|Toggle secret push protection')"
label-position="hidden"
@change="togglePreReceiveSecretDetection"
/>

View File

@ -52,7 +52,7 @@ export const CLUSTER_IMAGE_SCANNING_NAME = s__('ciReport|Cluster Image Scanning'
export const PRE_RECEIVE_SECRET_DETECTION = 'pre_receive_secret_detection';
export const PRE_RECEIVE_SECRET_DETECTION_NAME = __('Pre-receive Secret Detection');
export const PRE_RECEIVE_SECRET_DETECTION_NAME = __('Secret push protection');
export const SCANNER_NAMES_MAP = {
SAST: SAST_SHORT_NAME,

View File

@ -126,12 +126,12 @@ export default {
</script>
<template>
<div class="gl-md-display-flex row-content-block">
<!-- `gl-w-full gl-md-w-15` forces fixed width needed to prevent
filtered component to grow beyond available width -->
<div
class="gl-display-flex gl-flex-direction-column gl-md-flex-direction-row gl-gap-3 row-content-block"
>
<gl-filtered-search
v-model="internalFilter"
class="gl-w-full gl-md-w-15 gl-mr-4 gl-flex-grow-1"
class="gl-flex-grow-1 gl-min-w-0"
:placeholder="__('Filter results')"
:available-tokens="tokens"
@submit="submitSearch"
@ -139,10 +139,8 @@ export default {
/>
<gl-sorting
data-testid="registry-sort-dropdown"
class="gl-mt-3 gl-md-mt-0 gl-w-full gl-md-w-auto"
dropdown-class="gl-w-full"
dropdown-toggle-class="!gl-shadow-inner-1-gray-400"
sort-direction-toggle-class="!gl-shadow-inner-1-gray-400"
block
:text="sortText"
:is-ascending="isSortAscending"
:sort-direction-tool-tip="sortDirectionData.tooltip"

View File

@ -92,9 +92,12 @@
.wiki-list {
min-height: 30px;
&:hover {
&:hover,
&.active {
background: var(--gray-50, $gray-50);
}
&:hover {
a {
color: $black;
}

View File

@ -35,7 +35,7 @@ module DiffHelper
options[:paths] = params.values_at(:old_path, :new_path)
options[:use_extra_viewer_as_main] = false
if Feature.enabled?(:large_ipynb_diffs, @project) && params[:file_identifier]&.include?('.ipynb')
if params[:file_identifier]&.include?('.ipynb')
options[:max_patch_bytes_for_file_extension] = {
'.ipynb' => 1.megabyte
}

View File

@ -271,7 +271,7 @@ module MergeRequestsHelper
def merge_request_source_branch(merge_request)
fork_icon = if merge_request.for_fork?
title = _('The source project is a fork')
content_tag(:span, class: 'gl-align-middle gl-mr-n2 has-tooltip', title: title) do
content_tag(:span, class: 'gl-align-middle -gl-mr-2 has-tooltip', title: title) do
sprite_icon('fork', size: 12, css_class: 'gl-ml-1 has-tooltip')
end
else

View File

@ -12,6 +12,24 @@ module Emails
)
end
def bulk_import_complete(user_id, bulk_import_id)
user = User.find(user_id)
@bulk_import = BulkImport.find(bulk_import_id)
@bulk_import_entity = @bulk_import.entities.find_by(source_type: 'group_entity') # rubocop:disable CodeReuse/ActiveRecord -- Move this to BulkImport model
@hostname = @bulk_import.configuration.url
@source_group = @bulk_import_entity.source_full_path
title = safe_format(
s_('BulkImport|Import of %{source_group} from %{hostname}'),
hostname: @hostname,
source_group: @source_group
)
email_with_layout(
to: user.notification_email_or_default,
subject: subject(title)
)
end
def bulk_import_csv_user_mapping(user_id, group_id, success_count, failed_count = 0)
user = User.find(user_id)
@group = Group.find(group_id)

View File

@ -357,6 +357,12 @@ class NotifyPreview < ActionMailer::Preview
Notify.github_gists_import_errors_email(user.id, { '12345' => 'Snippet maximum file count exceeded', '67890' => 'error message 2' }).message
end
def bulk_import_complete
bulk_import = BulkImport.last
Notify.bulk_import_complete(user.id, bulk_import.id)
end
def bulk_import_csv_user_mapping_success
Notify.bulk_import_csv_user_mapping(user.id, group.id, 94125, 0)
end

View File

@ -24,7 +24,7 @@ module Operations
before_destroy :ensure_no_associated_strategies
scope :for_name_like, -> (query) do
scope :for_name_like, ->(query) do
fuzzy_search(query, [:name], use_minimum_char_limit: false)
end

View File

@ -6,9 +6,9 @@ class Packages::BuildInfo < ApplicationRecord
scope :pluck_pipeline_ids, -> { pluck(:pipeline_id) }
scope :without_empty_pipelines, -> { where.not(pipeline_id: nil) }
scope :order_by_pipeline_id, -> (direction) { order(pipeline_id: direction) }
scope :with_pipeline_id_less_than, -> (pipeline_id) { where("#{table_name}.pipeline_id < ?", pipeline_id) }
scope :with_pipeline_id_greater_than, -> (pipeline_id) { where("#{table_name}.pipeline_id > ?", pipeline_id) }
scope :order_by_pipeline_id, ->(direction) { order(pipeline_id: direction) }
scope :with_pipeline_id_less_than, ->(pipeline_id) { where("#{table_name}.pipeline_id < ?", pipeline_id) }
scope :with_pipeline_id_greater_than, ->(pipeline_id) { where("#{table_name}.pipeline_id > ?", pipeline_id) }
def self.supported_keyset_orderings
{ id: [:desc] }

View File

@ -18,7 +18,7 @@ class Packages::Maven::Metadatum < ApplicationRecord
validate :maven_package_type
scope :for_package_ids, -> (package_ids) { where(package_id: package_ids) }
scope :for_package_ids, ->(package_ids) { where(package_id: package_ids) }
scope :with_path, ->(path) { where(path: path) }
scope :order_created, -> { reorder('created_at ASC') }

View File

@ -54,7 +54,7 @@ class Packages::Package < ApplicationRecord
has_one :terraform_module_metadatum, inverse_of: :package, class_name: 'Packages::TerraformModule::Metadatum'
has_many :build_infos, inverse_of: :package
has_many :pipelines, through: :build_infos, disable_joins: true
has_many :matching_package_protection_rules, -> (package) { where(package_type: package.package_type).for_package_name(package.name) }, through: :project, source: :package_protection_rules
has_many :matching_package_protection_rules, ->(package) { where(package_type: package.package_type).for_package_name(package.name) }, through: :project, source: :package_protection_rules
accepts_nested_attributes_for :maven_metadatum
@ -126,7 +126,7 @@ class Packages::Package < ApplicationRecord
scope :search_by_name, ->(query) { fuzzy_search(query, [:name], use_minimum_char_limit: false) }
scope :with_version, ->(version) { where(version: version) }
scope :without_version_like, -> (version) { where.not(arel_table[:version].matches(version)) }
scope :without_version_like, ->(version) { where.not(arel_table[:version].matches(version)) }
scope :with_package_type, ->(package_type) { where(package_type: package_type) }
scope :without_package_type, ->(package_type) { where.not(package_type: package_type) }
scope :displayable, -> { with_status(DISPLAYABLE_STATUSES) }
@ -136,7 +136,7 @@ class Packages::Package < ApplicationRecord
scope :including_dependency_links, -> { includes(dependency_links: :dependency) }
scope :including_dependency_links_with_nuget_metadatum, -> { includes(dependency_links: [:dependency, :nuget_metadatum]) }
scope :with_composer_target, -> (target) do
scope :with_composer_target, ->(target) do
includes(:composer_metadatum)
.joins(:composer_metadatum)
.where(Packages::Composer::Metadatum.table_name => { target_sha: target })

View File

@ -11,7 +11,7 @@ class Packages::Tag < ApplicationRecord
NUGET_TAGS_SEPARATOR = ' ' # https://docs.microsoft.com/en-us/nuget/reference/nuspec#tags
scope :preload_package, -> { preload(:package) }
scope :with_name, -> (name) { where(name: name) }
scope :with_name, ->(name) { where(name: name) }
def self.for_package_ids(package_ids)
where(package_id: package_ids)

View File

@ -29,19 +29,19 @@ class PersonalAccessToken < ApplicationRecord
scope :expiring_and_not_notified, ->(date) { where(["revoked = false AND expire_notification_delivered = false AND expires_at >= CURRENT_DATE AND expires_at <= ?", date]) }
scope :expired_today_and_not_notified, -> { where(["revoked = false AND expires_at = CURRENT_DATE AND after_expiry_notification_delivered = false"]) }
scope :inactive, -> { where("revoked = true OR expires_at < CURRENT_DATE") }
scope :last_used_before_or_unused, -> (date) { where("personal_access_tokens.created_at < :date AND (last_used_at < :date OR last_used_at IS NULL)", date: date) }
scope :last_used_before_or_unused, ->(date) { where("personal_access_tokens.created_at < :date AND (last_used_at < :date OR last_used_at IS NULL)", date: date) }
scope :with_impersonation, -> { where(impersonation: true) }
scope :without_impersonation, -> { where(impersonation: false) }
scope :revoked, -> { where(revoked: true) }
scope :not_revoked, -> { where(revoked: [false, nil]) }
scope :for_user, -> (user) { where(user: user) }
scope :for_users, -> (users) { where(user: users) }
scope :for_user, ->(user) { where(user: user) }
scope :for_users, ->(users) { where(user: users) }
scope :preload_users, -> { preload(:user) }
scope :order_expires_at_asc_id_desc, -> { reorder(expires_at: :asc, id: :desc) }
scope :project_access_token, -> { includes(:user).references(:user).merge(User.project_bot) }
scope :owner_is_human, -> { includes(:user).references(:user).merge(User.human) }
scope :last_used_before, -> (date) { where("last_used_at <= ?", date) }
scope :last_used_after, -> (date) { where("last_used_at >= ?", date) }
scope :last_used_before, ->(date) { where("last_used_at <= ?", date) }
scope :last_used_after, ->(date) { where("last_used_at >= ?", date) }
scope :expiring_and_not_notified_without_impersonation, -> { where(["(revoked = false AND expire_notification_delivered = false AND expires_at >= CURRENT_DATE AND expires_at <= :date) and impersonation = false", { date: DAYS_TO_EXPIRE.days.from_now.to_date }]) }
validates :scopes, presence: true

View File

@ -649,7 +649,7 @@ class Project < ApplicationRecord
# Sometimes queries (e.g. using CTEs) require explicit disambiguation with table name
scope :projects_order_id_asc, -> { reorder(self.arel_table['id'].asc) }
scope :projects_order_id_desc, -> { reorder(self.arel_table['id'].desc) }
scope :order_by_storage_size, -> (direction) do
scope :order_by_storage_size, ->(direction) do
build_keyset_order_on_joined_column(
scope: joins(:statistics),
attribute_name: 'project_statistics_storage_size',
@ -659,7 +659,7 @@ class Project < ApplicationRecord
)
end
scope :sorted_by_similarity_desc, -> (search, full_path_only: false) do
scope :sorted_by_similarity_desc, ->(search, full_path_only: false) do
rules = if full_path_only
[{ column: arel_table["path"], multiplier: 1 }]
else
@ -713,9 +713,9 @@ class Project < ApplicationRecord
scope :with_group, -> { includes(:group) }
scope :with_import_state, -> { includes(:import_state) }
scope :include_project_feature, -> { includes(:project_feature) }
scope :include_integration, -> (integration_association_name) { includes(integration_association_name) }
scope :with_integration, -> (integration_class) { joins(:integrations).merge(integration_class.all) }
scope :with_active_integration, -> (integration_class) { with_integration(integration_class).merge(integration_class.active) }
scope :include_integration, ->(integration_association_name) { includes(integration_association_name) }
scope :with_integration, ->(integration_class) { joins(:integrations).merge(integration_class.all) }
scope :with_active_integration, ->(integration_class) { with_integration(integration_class).merge(integration_class.active) }
scope :with_shared_runners_enabled, -> { where(shared_runners_enabled: true) }
# .with_slack_integration can generate poorly performing queries. It is intended only for UsagePing.
scope :with_slack_integration, -> { joins(:slack_integration) }
@ -763,12 +763,12 @@ class Project < ApplicationRecord
scope :with_package_registry_enabled, -> { with_feature_enabled(:package_registry) }
scope :with_issues_available_for_user, ->(current_user) { with_feature_available_for_user(:issues, current_user) }
scope :with_merge_requests_available_for_user, ->(current_user) { with_feature_available_for_user(:merge_requests, current_user) }
scope :with_issues_or_mrs_available_for_user, -> (user) do
scope :with_issues_or_mrs_available_for_user, ->(user) do
with_issues_available_for_user(user).or(with_merge_requests_available_for_user(user))
end
scope :with_merge_requests_enabled, -> { with_feature_enabled(:merge_requests) }
scope :with_remote_mirrors, -> { joins(:remote_mirrors).where(remote_mirrors: { enabled: true }) }
scope :with_limit, -> (maximum) { limit(maximum) }
scope :with_limit, ->(maximum) { limit(maximum) }
scope :with_group_runners_enabled, -> do
joins(:ci_cd_settings)
@ -788,14 +788,14 @@ class Project < ApplicationRecord
preload(:project_feature, :route, namespace: [:route, :owner])
}
scope :with_name, -> (name) { where(name: name) }
scope :created_by, -> (user) { where(creator: user) }
scope :imported_from, -> (type) { where(import_type: type) }
scope :with_name, ->(name) { where(name: name) }
scope :created_by, ->(user) { where(creator: user) }
scope :imported_from, ->(type) { where(import_type: type) }
scope :imported, -> { where.not(import_type: nil) }
scope :with_enabled_error_tracking, -> { joins(:error_tracking_setting).where(project_error_tracking_settings: { enabled: true }) }
scope :last_activity_before, -> (time) { where('projects.last_activity_at < ?', time) }
scope :last_activity_before, ->(time) { where('projects.last_activity_at < ?', time) }
scope :with_service_desk_key, -> (key) do
scope :with_service_desk_key, ->(key) do
# project_key is not indexed for now
# see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24063#note_282435524 for details
joins(:service_desk_setting).where('service_desk_settings.project_key' => key)
@ -815,8 +815,8 @@ class Project < ApplicationRecord
.order(id: :desc)
end
scope :in_organization, -> (organization) { where(organization: organization) }
scope :by_project_namespace, -> (project_namespace) { where(project_namespace_id: project_namespace) }
scope :in_organization, ->(organization) { where(organization: organization) }
scope :by_project_namespace, ->(project_namespace) { where(project_namespace_id: project_namespace) }
scope :not_a_fork, -> {
left_outer_joins(:fork_network_member).where(fork_network_member: { forked_from_project_id: nil })
@ -945,7 +945,7 @@ class Project < ApplicationRecord
# We require an alias to the project_mirror_data_table in order to use import_state in our queries
scope :joins_import_state, -> { joins("INNER JOIN project_mirror_data import_state ON import_state.project_id = projects.id") }
scope :for_group, -> (group) { where(group: group) }
scope :for_group, ->(group) { where(group: group) }
scope :for_group_and_its_subgroups, ->(group) { where(namespace_id: group.self_and_descendants.select(:id)) }
scope :for_group_and_its_ancestor_groups, ->(group) { where(namespace_id: group.self_and_ancestors.select(:id)) }
scope :is_importing, -> { with_import_state.where(import_state: { status: %w[started scheduled] }) }

View File

@ -7,7 +7,7 @@ class ProjectDailyStatistic < ApplicationRecord
counter_attribute :fetch_count
scope :of_project, -> (project) { where(project: project) }
scope :of_project, ->(project) { where(project: project) }
scope :of_last_30_days, -> { where('date >= ?', 29.days.ago.utc.to_date) }
scope :sorted_by_date_desc, -> { order(project_id: :desc, date: :desc) }
scope :sum_fetch_count, -> { sum(:fetch_count) }

View File

@ -50,7 +50,6 @@ class ProjectExportJob < ApplicationRecord
private
def audit_project_exported
return if Feature.disabled?(:export_audit_events, user)
return if exported_by_admin? && Gitlab::CurrentSettings.silent_admin_exports_enabled?
audit_context = {

View File

@ -12,7 +12,7 @@ class ProjectFeatureUsage < ApplicationRecord
belongs_to :project
validates :project, presence: true
scope :with_jira_dvcs_integration_enabled, -> (cloud: true) do
scope :with_jira_dvcs_integration_enabled, ->(cloud: true) do
where.not(jira_dvcs_integration_field(cloud: cloud) => nil)
end

View File

@ -15,8 +15,8 @@ class ProjectGroupLink < ApplicationRecord
validate :different_group
scope :non_guests, -> { where('group_access > ?', Gitlab::Access::GUEST) }
scope :in_group, -> (group_ids) { where(group_id: group_ids) }
scope :for_projects, -> (project_ids) { where(project_id: project_ids) }
scope :in_group, ->(group_ids) { where(group_id: group_ids) }
scope :for_projects, ->(project_ids) { where(project_id: project_ids) }
alias_method :shared_with_group, :group
alias_method :shared_from, :project

View File

@ -38,7 +38,7 @@ class ProjectStatistics < ApplicationRecord
scope :for_project_ids, ->(project_ids) { where(project_id: project_ids) }
scope :for_namespaces, -> (namespaces) { where(namespace: namespaces) }
scope :for_namespaces, ->(namespaces) { where(namespace: namespaces) }
def total_repository_size
repository_size + lfs_objects_size

View File

@ -32,7 +32,7 @@ module Projects
validates :relation, presence: true, length: { maximum: 255 }, uniqueness: { scope: :project_export_job_id }
validates :status, numericality: { only_integer: true }, presence: true
scope :by_relation, -> (relation) { where(relation: relation) }
scope :by_relation, ->(relation) { where(relation: relation) }
STATUS = {
queued: 0,

View File

@ -19,6 +19,14 @@ module Projects
end
mount_uploader :export_file, ImportExportUploader
# This causes CarrierWave v1 and v3 (but not v2) to upload the file to
# object storage *after* the database entry has been committed to the
# database. This avoids idling in a transaction. Similar to `ImportExportUpload`.
if Gitlab::Utils.to_boolean(ENV.fetch('ENABLE_STORE_EXPORT_FILE_AFTER_COMMIT', true))
skip_callback :save, :after, :store_export_file!
set_callback :commit, :after, :store_export_file!
end
end
end
end

View File

@ -27,7 +27,7 @@ module Projects
scope :without_assigned_projects, -> { where(total_projects_count: 0) }
scope :order_by_non_private_projects_count, -> { order(non_private_projects_count: :desc).order(id: :asc) }
scope :reorder_by_similarity, -> (search) do
scope :reorder_by_similarity, ->(search) do
order_expression = Gitlab::Database::SimilarityScore.build_expression(
search: search,
rules: [

View File

@ -33,9 +33,9 @@ class PrometheusAlert < ApplicationRecord
delegate :title, :query, to: :prometheus_metric
scope :for_metric, -> (metric) { where(prometheus_metric: metric) }
scope :for_project, -> (project) { where(project_id: project) }
scope :for_environment, -> (environment) { where(environment_id: environment) }
scope :for_metric, ->(metric) { where(prometheus_metric: metric) }
scope :for_project, ->(project) { where(project_id: project) }
scope :for_environment, ->(environment) { where(environment_id: environment) }
scope :get_environment_id, -> { select(:environment_id).pluck(:environment_id) }
def self.distinct_projects

View File

@ -12,7 +12,7 @@ class PrometheusAlertEvent < ApplicationRecord
delegate :title, :prometheus_metric_id, to: :prometheus_alert
scope :for_environment, -> (environment) do
scope :for_environment, ->(environment) do
joins(:prometheus_alert).where(prometheus_alerts: { environment_id: environment })
end

View File

@ -18,13 +18,13 @@ class PrometheusMetric < ApplicationRecord
validates :project, presence: true, unless: :common?
validates :project, absence: true, if: :common?
scope :for_dashboard_path, -> (dashboard_path) { where(dashboard_path: dashboard_path) }
scope :for_project, -> (project) { where(project: project) }
scope :for_group, -> (group) { where(group: group) }
scope :for_title, -> (title) { where(title: title) }
scope :for_y_label, -> (y_label) { where(y_label: y_label) }
scope :for_identifier, -> (identifier) { where(identifier: identifier) }
scope :not_identifier, -> (identifier) { where.not(identifier: identifier) }
scope :for_dashboard_path, ->(dashboard_path) { where(dashboard_path: dashboard_path) }
scope :for_project, ->(project) { where(project: project) }
scope :for_group, ->(group) { where(group: group) }
scope :for_title, ->(title) { where(title: title) }
scope :for_y_label, ->(y_label) { where(y_label: y_label) }
scope :for_identifier, ->(identifier) { where(identifier: identifier) }
scope :not_identifier, ->(identifier) { where.not(identifier: identifier) }
scope :common, -> { where(common: true) }
scope :ordered, -> { reorder(created_at: :asc) }

View File

@ -112,7 +112,6 @@ module Groups
end
def audit_export
return if Feature.disabled?(:export_audit_events, current_user)
return if exported_by_admin && Gitlab::CurrentSettings.silent_admin_exports_enabled?
audit_context = {

View File

@ -6,6 +6,8 @@ module Issues
include IncidentManagement::UsageData
include IssueTypeHelpers
EpicAssignmentError = Class.new(::ArgumentError)
def hook_data(issue, action, old_associations: {})
hook_data = issue.to_hook_data(current_user, old_associations: old_associations)
hook_data[:object_attributes][:action] = action

View File

@ -17,12 +17,11 @@
.form-group{ data: { testid: 'bulk-import' } }
= f.label :bulk_import, s_('AdminSettings|Allow migrating GitLab groups and projects by direct transfer'), class: 'gl-font-weight-bold'
= f.gitlab_ui_checkbox_component :bulk_import_enabled, s_('AdminSettings|Enabled')
- if Feature.enabled?(:export_audit_events, current_user)
.form-group{ data: { testid: 'silent-admin-exports' } }
- tag_pair_silent_admin_exports = tag_pair(link_to('', help_page_path('administration/settings/import_and_export_settings', anchor: 'enable-silent-admin-exports'), target: '_blank', rel: 'noopener noreferrer'), :silent_admin_exports_link_start, :silent_admin_exports_link_end)
- silent_admin_exports_label_text = safe_format(s_('AdminSettings|Silent exports by admins %{silent_admin_exports_link_start}%{icon}%{silent_admin_exports_link_end}'), tag_pair_silent_admin_exports, icon: sprite_icon('question-o'))
= f.label :silent_admin_exports_enabled, silent_admin_exports_label_text, class: 'gl-font-weight-bold'
= f.gitlab_ui_checkbox_component :silent_admin_exports_enabled, s_('AdminSettings|Enabled')
.form-group{ data: { testid: 'silent-admin-exports' } }
- tag_pair_silent_admin_exports = tag_pair(link_to('', help_page_path('administration/settings/import_and_export_settings', anchor: 'enable-silent-admin-exports'), target: '_blank', rel: 'noopener noreferrer'), :silent_admin_exports_link_start, :silent_admin_exports_link_end)
- silent_admin_exports_label_text = safe_format(s_('AdminSettings|Silent exports by admins %{silent_admin_exports_link_start}%{icon}%{silent_admin_exports_link_end}'), tag_pair_silent_admin_exports, icon: sprite_icon('question-o'))
= f.label :silent_admin_exports_enabled, silent_admin_exports_label_text, class: 'gl-font-weight-bold'
= f.gitlab_ui_checkbox_component :silent_admin_exports_enabled, s_('AdminSettings|Enabled')
.form-group
= f.label :max_export_size, _('Maximum export size (MiB)'), class: 'label-light'
= f.number_field :max_export_size, class: 'form-control gl-form-input', title: _('Maximum size of export files.'), data: { toggle: 'tooltip', container: 'body' }

View File

@ -1,3 +1,4 @@
= gl_tabs_nav({ class: 'gl-flex-grow-1 gl-border-0', data: { testid: 'admin-users-tabs' } }) do
= gl_tab_link_to s_('AdminUsers|Users'), admin_users_path
= render_if_exists 'admin/users/role_promotion_requests_tab'
= gl_tab_link_to s_('AdminUsers|Cohorts'), admin_cohorts_path

View File

@ -0,0 +1,24 @@
- header_style = 'font-size:24px; text-align:center; line-height:30px;'
- text_style = 'font-size:16px; text-align:center; line-height:24px; margin-top: 24px;'
- button_style = 'border: 1px solid #694cc0; border-radius: 4px; font-size: 14px; padding: 8px 16px; background-color: #7b58cf; color: #fff; cursor: pointer;'
- strong_tag_pair = tag_pair(tag.strong, :strong_open, :strong_close)
- strong_color_tag_pair = tag_pair(tag.strong(style: 'color: #7b58cf'), :strong_color_open, :strong_color_close)
- destination_group = @bulk_import_entity.full_path_with_fallback
%h1{ style: header_style }
= s_('BulkImport|Import completed')
%p{ style: text_style }
= safe_format(s_('BulkImport|The import of %{strong_open}%{source_group}%{strong_close} from %{strong_open}%{hostname}%{strong_close} to %{strong_color_open}%{destination_group}%{strong_color_close} is complete. You can view the results of the import.'),
strong_tag_pair,
strong_color_tag_pair,
source_group: @source_group,
hostname: @hostname,
destination_group: destination_group)
%p{ style: text_style }
= link_to history_import_bulk_import_url(@bulk_import.id), target: '_blank', rel: 'noopener noreferrer' do
%button{ type: 'button', style: button_style }
= s_('BulkImport|View import results')

View File

@ -0,0 +1,7 @@
<% destination_group = @bulk_import_entity.full_path_with_fallback %>
<%= s_('BulkImport|Import completed') %>
<%= safe_format(s_('BulkImport|The import of %{strong_open}%{source_group}%{strong_close} from %{strong_open}%{hostname}%{strong_close} to %{strong_color_open}%{destination_group}%{strong_color_close} is complete. You can view the results of the import.'), strong_open: '', strong_close: '', strong_color_open: '', strong_color_close: '', source_group: @source_group, hostname: @hostname, destination_group: destination_group) %>
<%= s_('BulkImport|View import results') %>: <%= history_import_bulk_import_url(@bulk_import.id) %>

View File

@ -1,7 +1,7 @@
- header_style = 'font-size:24px; text-align:center; line-height:30px;'
- text_style = 'font-size:16px; text-align:center; line-height:24px; margin-top: 24px;'
- error_style = 'color:#c91c00;'
- button_style = 'border-color: #694cc0; border-style: solid; border-width: 1px; border-radius: 4px; font-size: 14px; padding: 8px 16px; background-color: #7b58cf; color: #fff; cursor: pointer;'
- button_style = 'border: 1px solid #694cc0; border-radius: 4px; font-size: 14px; padding: 8px 16px; background-color: #7b58cf; color: #fff; cursor: pointer;'
- strong_tag_pair = tag_pair(tag.strong(style: 'color: #7b58cf'), :strong_open, :strong_close)

View File

@ -1,4 +1,4 @@
%h4.gl-heading-4= _('Repository cleanup')
%h5.gl-heading-4= _('Repository cleanup')
%p.gl-text-secondary
- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe
- git_filter_link_start = link_start % { url: 'https://github.com/newren/git-filter-repo' }
@ -17,7 +17,7 @@
= gitlab_ui_form_for @project, url: url, method: :post, authenticity_token: true, html: { class: 'js-requires-input' } do |f|
%fieldset.gl-mt-0.gl-mb-3
.gl-mb-3
%h5.gl-mt-0
%h6.gl-mt-0
= _("Upload commit-map file")
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-choose-file' }) do
= _("Choose a file")

View File

@ -0,0 +1,8 @@
%h5.gl-heading-4= s_('ProjectMaintenance|Remove blobs')
%p.gl-text-secondary
= s_('ProjectMaintenance|Provide a list of blob object IDs to be removed.')
= link_to s_('ProjectMaintenance|How do I get a list of object IDs?'), help_page_path('user/project/repository/reducing_the_repo_size_using_git')
%p.gl-text-secondary
= s_('ProjectMaintenance|Housekeeping will need to be triggered manually afterwards to remove old versions of the file.')
.js-maintenance-remove-blobs

View File

@ -15,4 +15,7 @@
- link_end = '</a>'.html_safe
= s_('ProjectMaintenance| To ensure that a full backup is available in case changes need to be restored, you should make an %{docs_link_start}export of the project%{docs_link_end}.').html_safe % { docs_link_start: docs_link_start, docs_link_end: link_end }
- if current_user.can?(:owner_access, @project) && Feature.enabled?(:rewrite_history_ui, @project)
= render "projects/maintenance/remove_blobs"
= render "projects/maintenance/cleanup"

View File

@ -78,7 +78,7 @@
= sprite_icon('issues', size: 14, css_class: 'gl-mr-2')
= badge_count(project.open_issues_count)
.gl-display-flex.gl-align-items-center.gl-gap-2.gl-mr-n2
.gl-display-flex.gl-align-items-center.gl-gap-2.-gl-mr-2
- if show_pipeline_status_icon && last_pipeline.present?
- pipeline_path = pipelines_project_commit_path(project.pipeline_status.project, project.pipeline_status.sha, ref: project.pipeline_status.ref)
%span.icon-wrapper.pipeline-status

View File

@ -1,7 +1,7 @@
- wiki_path = wiki_page_path(@wiki, wiki_page)
%li{ class: active_when(params[:id] == wiki_page.slug) }
.gl-relative.gl-flex.gl-items-center.js-wiki-list-toggle.wiki-list.gl-px-3.gl-rounded-base{ data: { testid: 'wiki-list' } }
%li
.gl-relative.gl-flex.gl-items-center.js-wiki-list-toggle.wiki-list.gl-px-3.gl-rounded-base{ data: { testid: 'wiki-list' }, class: active_when(params[:id] == wiki_page.slug) }
= link_to wiki_path, class: 'gl-str-truncated', data: { testid: 'wiki-page-link', qa_page_name: wiki_page.human_title } do
= wiki_page.human_title
- plus_tooltip_title = safe_format(s_('Wiki|Create a new page under "%{page_title}"'), { page_title: wiki_page.human_title })

View File

@ -1,7 +1,7 @@
- wiki_path = wiki_page_path(@wiki, wiki_directory)
%li{ data: { testid: 'wiki-directory-content' } }
.gl-relative.gl-flex.gl-items-center.js-wiki-list-toggle.wiki-list.gl-px-3.gl-rounded-base.gl-cursor-pointer{ data: { testid: 'wiki-list' } }<
.gl-relative.gl-flex.gl-items-center.js-wiki-list-toggle.wiki-list.gl-px-3.gl-rounded-base.gl-cursor-pointer{ data: { testid: 'wiki-list' }, class: active_when(params[:id] == wiki_directory.slug) }
= link_to wiki_path, data: { testid: 'wiki-dir-page-link', qa_page_name: wiki_directory.title }, class: 'gl-str-truncated ' do
= wiki_directory.title
- plus_tooltip_title = safe_format(s_('Wiki|Create a new page under "%{page_title}"'), { page_title: wiki_directory.title })

View File

@ -1,9 +1,9 @@
---
name: export_audit_events
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/294168
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/151278
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/458597
milestone: '17.0'
group: group::import and integrate
type: wip
name: rewrite_history_ui
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/450701
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/153824
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/462999
milestone: '17.1'
group: group::source code
type: beta
default_enabled: false

View File

@ -1,8 +0,0 @@
---
name: large_ipynb_diffs
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/113370
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/393886
milestone: '15.10'
type: development
group: group::incubation
default_enabled: false

View File

@ -1,75 +0,0 @@
# frozen_string_literal: true
require 'redis-client'
# This patch can be dropped once https://github.com/redis-rb/redis-client/pull/197
# is released and merged.
if Gem::Version.new(RedisClient::VERSION) > Gem::Version.new('0.22.1') # rubocop:disable Style/GuardClause -- This is easier to read
raise 'New version of redis-client detected, please remove this file'
end
# rubocop:disable Gitlab/ModuleWithInstanceVariables -- This is an upstream gem
# rubocop:disable Style/GuardClause -- This is an upstream gem
class RedisClient
module ConnectionMixin
def call(command, timeout)
@pending_reads += 1
write(command)
result = read(connection_timeout(timeout))
@pending_reads -= 1
if result.is_a?(Error)
result._set_command(command)
result._set_config(config)
raise result
else
result
end
end
def call_pipelined(commands, timeouts, exception: true)
first_exception = nil
size = commands.size
results = Array.new(commands.size)
@pending_reads += size
write_multi(commands)
size.times do |index|
timeout = timeouts && timeouts[index]
result = read(connection_timeout(timeout))
@pending_reads -= 1
# A multi/exec command can return an array of results.
# An error from a multi/exec command is handled in Multi#_coerce!.
if result.is_a?(Array)
result.each do |res|
res._set_config(config) if res.is_a?(Error)
end
elsif result.is_a?(Error)
result._set_command(commands[index])
result._set_config(config)
first_exception ||= result
end
results[index] = result
end
if first_exception && exception
raise first_exception
else
results
end
end
def connection_timeout(timeout)
return timeout unless timeout && timeout > 0
# Can't use the command timeout argument as the connection timeout
# otherwise it would be very racy. So we add the regular read_timeout on top
# to account for the network delay.
timeout + config.read_timeout
end
end
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
# rubocop:enable Style/GuardClause

View File

@ -6,3 +6,4 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/128010
milestone: '16.8'
queued_migration_version: 20240105144908
finalize_after: '2024-02-22'
finalized_by: 20240516140819

View File

@ -3,7 +3,7 @@ table_name: push_event_payloads
classes:
- PushEventPayload
feature_categories:
- user_profile
- source_code_management
description: Stores log of push events
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12463
milestone: '9.5'

View File

@ -1,10 +1,11 @@
---
table_name: work_item_related_link_restrictions
classes:
- WorkItems::RelatedLinkRestriction
- WorkItems::RelatedLinkRestriction
feature_categories:
- portfolio_management
- portfolio_management
description: Restrictions applied to related links.
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/133044
milestone: '16.5'
gitlab_schema: gitlab_main
sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/463469

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
# See https://docs.gitlab.com/ee/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class UpdateSubscriptionAddOnPurchasesStartedAtPrecision < Gitlab::Database::Migration[2.2]
milestone '17.1'
def up
change_column :subscription_add_on_purchases, :started_at, :date
end
def down
change_column :subscription_add_on_purchases, :started_at, :datetime_with_timezone
end
end

View File

@ -0,0 +1,27 @@
# frozen_string_literal: true
# See https://docs.gitlab.com/ee/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class FinalizeBackfillIssueSearchDataNamespaceId < Gitlab::Database::Migration[2.2]
milestone '17.1'
disable_ddl_transaction!
restrict_gitlab_migration gitlab_schema: :gitlab_main
MIGRATION = "BackfillIssueSearchDataNamespaceId"
def up
ensure_batched_background_migration_is_finished(
job_class_name: MIGRATION,
table_name: :issues,
column_name: :id,
job_arguments: [],
finalize: true
)
end
def down
# no-op
end
end

View File

@ -0,0 +1 @@
613d939f0d13e2045b001a95e7ee2ec885368f8503218a8ccd23a26cf4f1b9af

View File

@ -0,0 +1 @@
5e5b9c56e5421deb38e06530c8acdf706145d18400a2e26090f7aab453795e40

View File

@ -16717,7 +16717,7 @@ CREATE TABLE subscription_add_on_purchases (
purchase_xid text NOT NULL,
last_assigned_users_refreshed_at timestamp with time zone,
trial boolean DEFAULT false NOT NULL,
started_at timestamp with time zone,
started_at date,
CONSTRAINT check_3313c4d200 CHECK ((char_length(purchase_xid) <= 255))
);

View File

@ -408,7 +408,7 @@ Audit event types belong to the following product categories.
| Name | Description | Saved to database | Streamed | Introduced in | Scope |
|:------------|:------------|:------------------|:---------|:--------------|:--------------|
| [`skip_pre_receive_secret_detection`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/147855) | Triggered when pre-receive secret detection is skipped by the user| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [16.11](https://gitlab.com/gitlab-org/gitlab/-/issues/441185) | Project |
| [`skip_pre_receive_secret_detection`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/147855) | Triggered when secret push protection is skipped by the user| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [16.11](https://gitlab.com/gitlab-org/gitlab/-/issues/441185) | Project |
### Security policy management

View File

@ -69,11 +69,9 @@ The same setting
## Enable silent admin exports
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/151278) in GitLab 17.0 [with a flag](../../administration/feature_flags.md) named `export_audit_events`. Disabled by default.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/153351) in GitLab 17.1. Feature flag `export_audit_events` removed.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/152143) for file export downloads in GitLab 17.1.
FLAG:
The availability of this feature is controlled by a feature flag. For more information, see the history.
Enable silent admin exports to prevent [audit events](../audit_event_reports.md) when
instance administrators trigger a [project or group file export](../../user/project/settings/import_export.md) or download the export file.
Exports from non-administrators still generate audit events.

View File

@ -8266,7 +8266,7 @@ Input type: `SetContainerScanningForRegistryInput`
### `Mutation.setPreReceiveSecretDetection`
Enable/disable pre-receive secret detection for the given project.
Enable/disable secret push protection for the given project.
Input type: `SetPreReceiveSecretDetectionInput`
@ -8275,7 +8275,7 @@ Input type: `SetPreReceiveSecretDetectionInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationsetprereceivesecretdetectionclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationsetprereceivesecretdetectionenable"></a>`enable` | [`Boolean!`](#boolean) | Desired status for pre-receive secret detection feature. |
| <a id="mutationsetprereceivesecretdetectionenable"></a>`enable` | [`Boolean!`](#boolean) | Desired status for secret push protection feature. |
| <a id="mutationsetprereceivesecretdetectionnamespacepath"></a>`namespacePath` | [`ID!`](#id) | Full path of the namespace (project). |
#### Fields

View File

@ -177,7 +177,7 @@ The CI/CD template migration involves the following steps:
- The name of the template should follow the `go` command, for example `format.yml`, `build.yml`, and `test.yml`.
- Create a new project, initialize a Git repository, add/commit all changes, set a remote origin and push.
Modify the URL for your CI/CD component project path.
- Create additional files to follow [best practice](index.md#best-practices):
- Create additional files as outlined in the guidance to [write a component](index.md#write-a-component):
`README.md`, `LICENSE.md`, `.gitlab-ci.yml`, `.gitignore`. The following shell commands
initialize the Go component structure:
@ -336,7 +336,7 @@ Follow the remaining steps in the [converting a CI/CD template into a component]
section to complete the migration:
1. Commit and push the changes, and verify the CI/CD pipeline results.
1. Follow [documentation best practices](index.md#best-practices) to update the `README.md` and `LICENSE.md` files.
1. Follow the guidance on [writing a component](index.md#write-a-component) to update the `README.md` and `LICENSE.md` files.
1. [Release the component](index.md#publish-a-new-release) and verify it in the CI/CD catalog.
1. Add the CI/CD component into your staging/production environment.

View File

@ -210,141 +210,7 @@ In this example, referencing the component with:
Pre-release versions are never fetched when referencing a version range. To fetch
a pre-release version, specify the full version, for example `1.0.1-rc`.
## CI/CD Catalog
DETAILS:
**Tier:** Free, Premium, Ultimate
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/407249) as an [experiment](../../policy/experiment-beta-support.md#experiment) in GitLab 16.1.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/432045) to [beta](../../policy/experiment-beta-support.md#beta) in GitLab 16.7.
> - [Made generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/454306) in GitLab 17.0.
The CI/CD Catalog is a list of projects with published CI/CD components you can use
to extend your CI/CD workflow.
Anyone can [create a component project](#create-a-component-project) and add it to
the CI/CD Catalog, or contribute to an existing project to improve the available components.
For a click-through demo, see [the CI/CD Catalog beta Product Tour](https://gitlab.navattic.com/cicd-catalog).
<!-- Demo published on 2024-01-24 -->
### View the CI/CD Catalog
To access the CI/CD Catalog and view the published components that are available to you:
1. On the left sidebar, select **Search or go to**.
1. Select **Explore**.
1. Select **CI/CD Catalog**.
Alternatively, if you are already in the [pipeline editor](../pipeline_editor/index.md)
in your project, you can select **Browse CI/CD Catalog**.
Visibility of components in the CI/CD catalog follows the component source project's
[visibility setting](../../user/public_access.md). Components with source projects set to:
- Private are visible only to users assigned at least the Guest role in the source component project.
- Internal are visible only to users logged into the GitLab instance.
- Public are visible to anyone with access to the GitLab instance.
### Publish a component project
To publish a component project in the CI/CD catalog, you must:
1. Set the project as a catalog project.
1. Publish a new release.
#### Set a component project as a catalog project
To make published versions of a component project visible in the CI/CD catalog,
you must set the project as a catalog project.
Prerequisites:
- You must have the Owner role in the project.
To set the project as a catalog project:
1. On the left sidebar, select **Search or go to** and find your project.
1. Select **Settings > General**.
1. Expand **Visibility, project features, permissions**.
1. Turn on the **CI/CD Catalog project** toggle.
The project only becomes findable in the catalog after you publish a new release.
#### Publish a new release
CI/CD components can be [used](#use-a-component) without being listed in the CI/CD catalog.
However, publishing a component's releases in the catalog makes it discoverable to other users.
Prerequisites:
- The project must:
- Be set as a [catalog project](#set-a-component-project-as-a-catalog-project).
- Have a [project description](../../user/project/working_with_projects.md#edit-project-name-description-and-avatar) defined.
- Have a `README.md` file in the root directory for the commit SHA of the tag being released.
- Have at least one [CI/CD component in the `templates/` directory](#directory-structure)
for the commit SHA of the tag being released.
To publish a new version of the component to the catalog:
1. Add a job to the project's `.gitlab-ci.yml` file that uses the [`release`](../yaml/index.md#release)
keyword to create the new release when a tag is created.
You should configure the tag pipeline to [test the components](#test-the-component) before
running the release job. For example:
```yaml
create-release:
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:latest
script: echo "Creating release $CI_COMMIT_TAG"
rules:
- if: $CI_COMMIT_TAG
release:
tag_name: $CI_COMMIT_TAG
description: "Release $CI_COMMIT_TAG of components in $CI_PROJECT_PATH"
```
1. Create a [new tag](../../user/project/repository/tags/index.md#create-a-tag) for the release,
which should trigger a tag pipeline that contains the job responsible for creating the release.
The tag must use [semantic versioning](#semantic-versioning).
After the release job completes successfully, the release is created and the new version
is published to the CI/CD catalog.
#### Semantic versioning
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/427286) in GitLab 16.10.
When tagging and [releasing new versions](#publish-a-new-release) of components to the Catalog,
you must use [semantic versioning](https://semver.org). Semantic versioning is the standard
for communicating that a change is a major, minor, patch, or other kind of change.
For example, `1.0.0`, `2.3.4`, and `1.0.0-alpha` are all valid semantic versions.
### Unpublish a component project
To remove a component project from the catalog, turn off the [**CI/CD Catalog resource**](#set-a-component-project-as-a-catalog-project)
toggle in the project settings.
WARNING:
This action destroys the metadata about the component project and its versions published
in the catalog. The project and its repository still exist, but are not visible in the catalog.
To publish the component project in the catalog again, you need to [publish a new release](#publish-a-new-release).
### Verified component creators
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/433443) in GitLab 16.11
Some CI/CD components are badged with an icon to show that the component was created
and is maintained by users verified by GitLab:
- GitLab-maintained (**{tanuki-verified}**): Components that are created and maintained by GitLab.
- GitLab Partner (**{partner-verified}**): Components that are created and maintained by
a GitLab-verified partner.
## Best practices
## Write a component
This section describes some best practices for creating high quality component projects.
@ -459,6 +325,18 @@ during component testing.
You can learn more in [examples for testing a component](examples.md#test-a-component).
### Avoid hard-coding instance or project-specific values
When [using another component](#use-a-component) in your component, use `$CI_SERVER_FQDN`
instead of your instance's Fully Qualified Domain Name (like `gitlab.com`).
When accessing the GitLab API in your component, use the `$CI_API_V4_URL` instead of the
full URL and path for your instance (like `https://gitlab.com/api/v4`).
These [predefined variables](../variables/predefined_variables.md)
ensure that your component also works when used on another instance, for example when using
[a GitLab.com component in a self-managed instance](#use-a-gitlabcom-component-in-a-self-managed-instance).
### Avoid using global keywords
Avoid using [global keywords](../yaml/index.md#global-keywords) in a component.
@ -601,6 +479,140 @@ In other cases, CI/CD variables might still be preferred. For example:
a component to match a user's project.
- Ask users to store sensitive values as [masked or protected CI/CD variables in project settings](../variables/index.md#define-a-cicd-variable-in-the-ui).
## CI/CD Catalog
DETAILS:
**Tier:** Free, Premium, Ultimate
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/407249) as an [experiment](../../policy/experiment-beta-support.md#experiment) in GitLab 16.1.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/432045) to [beta](../../policy/experiment-beta-support.md#beta) in GitLab 16.7.
> - [Made Generally Available](https://gitlab.com/gitlab-org/gitlab/-/issues/454306) in GitLab 17.0.
The CI/CD Catalog is a list of projects with published CI/CD components you can use
to extend your CI/CD workflow.
Anyone can [create a component project](#create-a-component-project) and add it to
the CI/CD Catalog, or contribute to an existing project to improve the available components.
For a click-through demo, see [the CI/CD Catalog beta Product Tour](https://gitlab.navattic.com/cicd-catalog).
<!-- Demo published on 2024-01-24 -->
### View the CI/CD Catalog
To access the CI/CD Catalog and view the published components that are available to you:
1. On the left sidebar, select **Search or go to**.
1. Select **Explore**.
1. Select **CI/CD Catalog**.
Alternatively, if you are already in the [pipeline editor](../pipeline_editor/index.md)
in your project, you can select **Browse CI/CD Catalog**.
Visibility of components in the CI/CD catalog follows the component source project's
[visibility setting](../../user/public_access.md). Components with source projects set to:
- Private are visible only to users assigned at least the Guest role in the source component project.
- Internal are visible only to users logged into the GitLab instance.
- Public are visible to anyone with access to the GitLab instance.
### Publish a component project
To publish a component project in the CI/CD catalog, you must:
1. Set the project as a catalog project.
1. Publish a new release.
#### Set a component project as a catalog project
To make published versions of a component project visible in the CI/CD catalog,
you must set the project as a catalog project.
Prerequisites:
- You must have the Owner role in the project.
To set the project as a catalog project:
1. On the left sidebar, select **Search or go to** and find your project.
1. Select **Settings > General**.
1. Expand **Visibility, project features, permissions**.
1. Turn on the **CI/CD Catalog project** toggle.
The project only becomes findable in the catalog after you publish a new release.
#### Publish a new release
CI/CD components can be [used](#use-a-component) without being listed in the CI/CD catalog.
However, publishing a component's releases in the catalog makes it discoverable to other users.
Prerequisites:
- The project must:
- Be set as a [catalog project](#set-a-component-project-as-a-catalog-project).
- Have a [project description](../../user/project/working_with_projects.md#edit-project-name-description-and-avatar) defined.
- Have a `README.md` file in the root directory for the commit SHA of the tag being released.
- Have at least one [CI/CD component in the `templates/` directory](#directory-structure)
for the commit SHA of the tag being released.
To publish a new version of the component to the catalog:
1. Add a job to the project's `.gitlab-ci.yml` file that uses the [`release`](../yaml/index.md#release)
keyword to create the new release when a tag is created.
You should configure the tag pipeline to [test the components](#test-the-component) before
running the release job. For example:
```yaml
create-release:
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:latest
script: echo "Creating release $CI_COMMIT_TAG"
rules:
- if: $CI_COMMIT_TAG
release:
tag_name: $CI_COMMIT_TAG
description: "Release $CI_COMMIT_TAG of components in $CI_PROJECT_PATH"
```
1. Create a [new tag](../../user/project/repository/tags/index.md#create-a-tag) for the release,
which should trigger a tag pipeline that contains the job responsible for creating the release.
The tag must use [semantic versioning](#semantic-versioning).
After the release job completes successfully, the release is created and the new version
is published to the CI/CD catalog.
#### Semantic versioning
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/427286) in GitLab 16.10.
When tagging and [releasing new versions](#publish-a-new-release) of components to the Catalog,
you must use [semantic versioning](https://semver.org). Semantic versioning is the standard
for communicating that a change is a major, minor, patch, or other kind of change.
For example, `1.0.0`, `2.3.4`, and `1.0.0-alpha` are all valid semantic versions.
### Unpublish a component project
To remove a component project from the catalog, turn off the [**CI/CD Catalog resource**](#set-a-component-project-as-a-catalog-project)
toggle in the project settings.
WARNING:
This action destroys the metadata about the component project and its versions published
in the catalog. The project and its repository still exist, but are not visible in the catalog.
To publish the component project in the catalog again, you need to [publish a new release](#publish-a-new-release).
### Verified component creators
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/433443) in GitLab 16.11
Some CI/CD components are badged with an icon to show that the component was created
and is maintained by users verified by GitLab:
- GitLab-maintained (**{tanuki-verified}**): Components that are created and maintained by GitLab.
- GitLab Partner (**{partner-verified}**): Components that are created and maintained by
a GitLab-verified partner.
## Convert a CI/CD template to a component
Any existing CI/CD template that you use in projects by using the `include:` syntax
@ -611,7 +623,7 @@ can be converted to a CI/CD component:
1. Create a YAML file in the component project according to the [directory structure](index.md#directory-structure).
1. Copy the content of the original template YAML file into the new component YAML file.
1. Refactor the new component's configuration to:
- Follow the [best practices](index.md#best-practices) for components.
- Follow the guidance on [writing a component](#write-a-component).
- Improve the configuration, for example by enabling [merge request pipelines](../pipelines/merge_request_pipelines.md)
or making it [more efficient](../pipelines/pipeline_efficiency.md).
1. Leverage the `.gitlab-ci.yml` in the components repository to [test changes to the component](index.md#test-the-component).

View File

@ -513,3 +513,39 @@ flow of how we construct a Chat prompt:
context to the request. It loops to up to 10 times until a final answer is reached.
(`*`) indicates that this step is part of the actual construction of the prompt
## Interpreting GitLab Duo Chat error codes
GitLab Duo Chat has error codes with specified meanings to assist in debugging.
Currently, they are only logged, but in the future, they will be displayed on the UI.
When developing for GitLab Duo Chat, please include these error codes when returning an error, especially a user-facing error.
### Error Code Format
The error codes follow the format: `<Layer Identifier><Four-digit Series Number>`.
For example:
- `M1001`: A network communication error in the monolith layer.
- `G2005`: A data formatting/processing error in the AI gateway layer.
- `A3010`: An authentication or data access permissions error in a third-party API.
### Error Code Layer Identifier
| Code | Layer |
|------|-----------------|
| M | Monolith |
| G | AI Gateway |
| A | Third-party API |
### Error Series
| Series | Type |
|--------|------------------------------------------------------------------------------|
| 1000 | Network communication errors |
| 2000 | Data formatting/processing errors |
| 3000 | Authentication and/or data access permission errors |
| 4000 | Code execution exceptions |
| 5000 | Bad configuration or bad parameters errors |
| 6000 | Semantic or inference errors (the model does not understand or hallucinates) |

View File

@ -52,7 +52,7 @@ in the catalog.
or ask one of the group owners to create an empty project for you.
1. Follow the [standard guide for creating components](../../ci/components/index.md).
1. Add a concise project description that clearly describes the capabilities offered by the component project.
1. Ensure that the [general best practices](../../ci/components/index.md#best-practices) are followed as well as
1. Ensure to follow the general guidance to [write a component](../../ci/components/index.md#write-a-component) as well as
[those for the official components](#best-practices-for-official-components).
1. Add a `LICENSE.md` file with the MIT license.
1. The project must have a `.gitlab-ci.yml` file that:
@ -103,7 +103,7 @@ Requirements for becoming a maintainer:
- Have a an in-depth understanding of the [CI/CD YAML syntax](../../ci/yaml/index.md) and features.
- Understand how CI components work and demonstrate experience developing them.
- Have a solid understanding of the components [best practices](../../ci/components/index.md#best-practices).
- Have a solid understanding of how to [write a component](../../ci/components/index.md#write-a-component).
How to join the `gitlab-components` group of general maintainers:

View File

@ -681,9 +681,8 @@ We also run our test suite against PostgreSQL 13 upon specific database library
| Merge requests | 14 (default version), 13 for DB library changes | 3.1 (default version) |
| `master` branch commits | 14 (default version), 13 for DB library changes | 3.1 (default version) |
| `maintenance` scheduled pipelines for the `master` branch (every even-numbered hour at XX:05) | 14 (default version), 13 for DB library changes | 3.1 (default version) |
| `maintenance` scheduled pipelines for the `ruby3_0` branch (every odd-numbered hour at XX:40) | 14 (default version), 13 for DB library changes | 3.0 |
| `maintenance` scheduled pipelines for the `ruby3_2` branch (every odd-numbered hour at XX:10) | 14 (default version), 13 for DB library changes | 3.2 |
| `nightly` scheduled pipelines for the `master` branch | 14 (default version), 13, 15, 16 | 3.1 (default version) |
| `nightly` scheduled pipelines for the `master` branch | 14 (default version), 13, 15, 16 | 3.1 (default version) |
For each current Ruby versions we're testing against with, we run
maintenance scheduled pipelines every 2 hours on their respective `ruby\d_\d`
@ -753,7 +752,8 @@ In general, pipelines for an MR fall into one of the following types (from short
A "pipeline type" is an abstract term that mostly describes the "critical path" (for example, the chain of jobs for which the sum
of individual duration equals the pipeline's duration).
We use these "pipeline types" in [metrics dashboards](https://app.periscopedata.com/app/gitlab/858266/GitLab-Pipeline-Durations) to detect what types and jobs need to be optimized first.
We use these "pipeline types" in [metrics dashboards](https://10az.online.tableau.com/#/site/gitlab/views/GitlabPipelineDurations/SuccessfulMergeRequestPipelineDurationHistogramsbyTypes?:iid=1)
to detect what types and jobs need to be optimized first.
An MR that touches multiple areas would be associated with the longest type applicable. For instance, an MR that touches backend
and frontend would fall into the "Frontend" pipeline type since this type takes longer to finish than the "Backend" pipeline type.

View File

@ -344,11 +344,15 @@ On the **Child issues and epics** section, under each epic name, hover over the
The number indicates all epics associated with the project, including issues
you might not have permission to.
### Add a new issue to an epic
### Add an issue to an epic
> - Maximum number of child issues and epics [changed](https://gitlab.com/gitlab-org/gitlab/-/issues/452111) to 100 in GitLab 17.0.
Add an existing issue to an epic, or create a new issue that's automatically
added to the epic.
The maximum number of direct child issues and epics is 100.
#### Add an existing issue to an epic
> - Minimum required role for the project [changed](https://gitlab.com/gitlab-org/gitlab/-/issues/382506) from Reporter to Guest in GitLab 15.8.

View File

@ -216,8 +216,8 @@ For members with `Minimal Access` in the selected group, their `Max Role` and `S
## User cap for groups
> - Behind a [feature flag](../../administration/feature_flags.md) named `saas_user_caps`. Disabled by default.
> - [Enabled on GitLab.com](https://gitlab.com/groups/gitlab-org/-/epics/9263) in GitLab 16.3.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/421693) in GitLab 17.1 Feature flag `saas_user_caps` removed.
For more information about user caps for GitLab self-managed, see [User cap](../../administration/settings/sign_up_restrictions.md#user-cap).

View File

@ -257,6 +257,9 @@ For example, in the following diagram:
```mermaid
%%{init: { "fontFamily": "GitLab Sans" }}%%
graph TB
accTitle: Automatic member removal
accDescr: How group membership of users is determined before sign in if group sync is set up.
subgraph SAML users
SAMLUserA[Sidney Jones]
SAMLUserB[Zhang Wei]
@ -283,6 +286,9 @@ graph TB
```mermaid
%%{init: { "fontFamily": "GitLab Sans" }}%%
graph TB
accTitle: Automatic member removal
accDescr: User membership for Sidney when she has not signed into group C, and group B has not configured group links.
subgraph GitLab users
GitLabUserA[Sidney Jones]
GitLabUserB[Zhang Wei]
@ -306,7 +312,11 @@ graph TB
```
```mermaid
%%{init: { "fontFamily": "GitLab Sans" }}%%
graph TB
accTitle: Automatic member removal
accDescr: How membership of Alex Garcia works once she has signed into a group that has group links enabled.
subgraph GitLab users
GitLabUserA[Sidney Jones]
GitLabUserB[Zhang Wei]

View File

@ -226,7 +226,11 @@ During the synchronization process, all new users:
The following diagram describes what happens when you add users to your SCIM app:
```mermaid
%%{init: { "fontFamily": "GitLab Sans" }}%%
graph TD
accTitle: Adding users to your SCIM application
accDescr: How GitLab determines whether or not to associate a SCIM identity with a user.
A[Add User to SCIM app] -->|IdP sends user info to GitLab| B(GitLab: Does the email exist?)
B -->|No| C[GitLab creates user with SCIM identity]
B -->|Yes| D(GitLab: Is the user part of the group?)
@ -285,7 +289,11 @@ NOTE:
Deprovisioning does not delete the GitLab user account.
```mermaid
%%{init: { "fontFamily": "GitLab Sans" }}%%
graph TD
accTitle: Deprovisioning users
accDescr: How removing users from your SCIM app removes them from GitLab groups.
A[Remove User from SCIM app] -->|IdP sends request to GitLab| B(GitLab: Is the user part of the group?)
B -->|No| C[Nothing to do]
B -->|Yes| D[GitLab removes user from GitLab group]

View File

@ -33,7 +33,11 @@ Subgroups can:
For example:
```mermaid
%%{init: { "fontFamily": "GitLab Sans" }}%%
graph TD
accTitle: Parent and subgroup nesting
accDescr: How parent groups, subgroups, and projects nest.
subgraph "Parent group"
subgraph "Subgroup A"
subgraph "Subgroup A1"
@ -136,7 +140,11 @@ Subgroup members can be:
1. [Indirect members](../../project/members/index.md#indirect-membership) include [inherited members](../../project/members/index.md#inherited-membership) and members of a group that was [invited to the subgroup or its ancestors](../manage.md#share-a-group-with-another-group).
```mermaid
%%{init: { "fontFamily": "GitLab Sans" }}%%
flowchart RL
accTitle: Subgroup membership
accDescr: How users become members of a subgroup - through direct, indirect, or inherited membership.
subgraph Group A
A(Direct member)
B{{Shared member}}

View File

@ -51,10 +51,11 @@ Product analytics uses the following tools:
The following diagram illustrates the product analytics flow:
```mermaid
---
title: Product Analytics flow
---
%%{init: { "fontFamily": "GitLab Sans" }}%%
flowchart TB
accTitle: Product Analytics flow
accDescr: How data is collected, processed, and visualized in dashboards.
subgraph Event collection
A([SDK]) --Send user data--> B[Snowplow Collector]
B --Pass data--> C[Snowplow Enricher]

View File

@ -248,3 +248,29 @@ The error can be avoided by:
- Using a reverse proxy to direct all requests from the source instance to the primary Geo node.
- Adding a local `hosts` file entry on the source to force the target host name to resolve to the Geo primary node's IP address.
- Configuring a pull mirror on the target instead.
## Pull or push mirror fails to update: `The project is not mirrored`
Pull and push mirrors fail to update when [GitLab Silent Mode](../../../../administration/silent_mode/index.md) is enabled.
When this happens, the option to allow mirroring on the UI is disabled.
An administrator can check to confirm that GitLab Silent Mode is disabled.
When mirroring fails due to Silent Mode the following are the debug steps:
- [Triggering the mirror using the API](pull.md#trigger-pipelines-for-mirror-updates) shows: `The project is not mirrored`.
- If pull or push mirror was already set up but there are no further updates on the mirrored repository,
confirm the [project's pull and push mirror details ans status](../../../../api/projects.md#get-a-projects-pull-mirror-details) are not recent as shown below. This indicates mirroring was paused and disabling GitLab Silent Mode restarts it automatically.
For example, if Silent Mode is what is impeding your imports, the output is similar to the following:
```json
"id": 1,
"update_status": "finished",
"url": "https://test.git"
"last_error": null,
"last_update_at": null,
"last_update_started_at": "2023-12-12T00:01:02.222Z",
"last_successful_update_at": null
```

View File

@ -288,6 +288,8 @@ module API
end
rescue ::ActiveRecord::RecordNotUnique
render_api_error!('Duplicated issue', 409)
rescue ::Issues::BaseService::EpicAssignmentError => error
render_api_error!(error.message, 422)
end
end

View File

@ -70,9 +70,9 @@ module Gitlab
type: 'container_scanning'
},
pre_receive_secret_detection: {
name: _('Pre-receive Secret Detection'),
name: _('Secret push protection'),
description: _('Block secrets such as keys and API tokens from being pushed to your repositories. ' \
'Pre-receive secret detection is triggered when commits are pushed to a repository. ' \
'Secret push protection is triggered when commits are pushed to a repository. ' \
'If any secrets are detected, the push is blocked.'),
help_path: Gitlab::Routing.url_helpers.help_page_path(
'user/application_security/secret_detection/pre_receive/index'),

View File

@ -12,15 +12,15 @@ module InitializerConnections
return yield if Gitlab::Utils.to_boolean(ENV['SKIP_RAISE_ON_INITIALIZE_CONNECTIONS'])
previous_connection_counts =
ActiveRecord::Base.connection_handler.connection_pool_list(ApplicationRecord.current_role).to_h do |pool|
[pool.db_config.name, pool.connections.size]
ActiveRecord::Base.connection_handler.connection_pool_list(ApplicationRecord.current_role).map do |pool|
pool.connections.size
end
yield
new_connection_counts =
ActiveRecord::Base.connection_handler.connection_pool_list(ApplicationRecord.current_role).to_h do |pool|
[pool.db_config.name, pool.connections.size]
ActiveRecord::Base.connection_handler.connection_pool_list(ApplicationRecord.current_role).map do |pool|
pool.connections.size
end
raise_database_connection_made_error unless previous_connection_counts == new_connection_counts

View File

@ -24,7 +24,7 @@ namespace :tw do
CodeOwnerRule.new('AI Framework', '@sselhorn'),
CodeOwnerRule.new('AI Model Validation', '@sselhorn'),
# CodeOwnerRule.new('Analytics Instrumentation', ''),
CodeOwnerRule.new('Anti-Abuse', '@phillipwells'),
# CodeOwnerRule.new('Anti-Abuse', ''),
CodeOwnerRule.new('Authentication', '@jglassman1'),
CodeOwnerRule.new('Authorization', '@jglassman1'),
# CodeOwnerRule.new('Billing and Subscription Management', ''),

View File

@ -3902,9 +3902,6 @@ msgstr ""
msgid "AdminSettings|Pause Elasticsearch indexing"
msgstr ""
msgid "AdminSettings|Pre-receive secret detection"
msgstr ""
msgid "AdminSettings|Prevent non-administrators from using the selected visibility levels for groups, projects and snippets."
msgstr ""
@ -3938,6 +3935,9 @@ msgstr ""
msgid "AdminSettings|Search with Elasticsearch enabled"
msgstr ""
msgid "AdminSettings|Secret Push Protection"
msgstr ""
msgid "AdminSettings|Select a group to use as a source of custom templates for new projects. %{link_start}Learn more%{link_end}."
msgstr ""
@ -4328,6 +4328,9 @@ msgstr ""
msgid "AdminUsers|Restore user access to the account, including web, Git and API."
msgstr ""
msgid "AdminUsers|Role Promotions"
msgstr ""
msgid "AdminUsers|Search by name, email, or username"
msgstr ""
@ -5195,21 +5198,21 @@ msgstr ""
msgid "Allow possible spam"
msgstr ""
msgid "Allow pre-receive secret detection"
msgstr ""
msgid "Allow project maintainers to configure repository mirroring"
msgstr ""
msgid "Allow projects and subgroups to override the group setting"
msgstr ""
msgid "Allow projects to enable pre-receive detection. This does not enable pre-receive secret detection. When you enable this feature, you accept the %{link_start}GitLab Testing Agreement%{link_end}."
msgid "Allow projects to enable secret push protection. This does not enable secret push protection. When you enable this feature, you accept the %{link_start}GitLab Testing Agreement%{link_end}."
msgstr ""
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow secret push protection"
msgstr ""
msgid "Allow this key to push to this repository"
msgstr ""
@ -8594,7 +8597,7 @@ msgstr ""
msgid "BlobViewer|View on %{environmentName}"
msgstr ""
msgid "Block secrets such as keys and API tokens from being pushed to your repositories. Pre-receive secret detection is triggered when commits are pushed to a repository. If any secrets are detected, the push is blocked."
msgid "Block secrets such as keys and API tokens from being pushed to your repositories. Secret push protection is triggered when commits are pushed to a repository. If any secrets are detected, the push is blocked."
msgstr ""
msgid "Block user"
@ -9593,6 +9596,9 @@ msgstr ""
msgid "BulkImport|History"
msgstr ""
msgid "BulkImport|Import completed"
msgstr ""
msgid "BulkImport|Import failed. '%{path}' already exists. Change the destination and try again."
msgstr ""
@ -9611,6 +9617,9 @@ msgstr ""
msgid "BulkImport|Import is finished. Pick another name for re-import"
msgstr ""
msgid "BulkImport|Import of %{source_group} from %{hostname}"
msgstr ""
msgid "BulkImport|Import with projects"
msgstr ""
@ -9707,6 +9716,9 @@ msgstr ""
msgid "BulkImport|Template / File-based import / Direct transfer"
msgstr ""
msgid "BulkImport|The import of %{strong_open}%{source_group}%{strong_close} from %{strong_open}%{hostname}%{strong_close} to %{strong_color_open}%{destination_group}%{strong_color_close} is complete. You can view the results of the import."
msgstr ""
msgid "BulkImport|This %{importable} was imported from another instance."
msgstr ""
@ -9716,6 +9728,9 @@ msgstr ""
msgid "BulkImport|Update of import statuses with realtime changes failed"
msgstr ""
msgid "BulkImport|View import results"
msgstr ""
msgid "BulkImport|Your imported groups and projects will appear here."
msgstr ""
@ -23378,9 +23393,6 @@ msgstr ""
msgid "GitLab Duo could not connect to the AI provider."
msgstr ""
msgid "GitLab Duo didn't respond. Try again? If it fails again, your request might be too large."
msgstr ""
msgid "GitLab Enterprise Edition"
msgstr ""
@ -26138,6 +26150,9 @@ msgstr ""
msgid "I'm signing up for GitLab because:"
msgstr ""
msgid "I'm sorry, I couldn't respond in time. Please try again."
msgstr ""
msgid "I'm sorry, I was not able to find any documentation to answer your question."
msgstr ""
@ -38884,12 +38899,6 @@ msgstr ""
msgid "Pre-defined push rules"
msgstr ""
msgid "Pre-receive Secret Detection"
msgstr ""
msgid "Pre-receive secret detection skipped via"
msgstr ""
msgid "PreScanVerification|(optional)"
msgstr ""
@ -39310,6 +39319,9 @@ msgstr ""
msgid "ProductAnalytics|All Sessions Compared"
msgstr ""
msgid "ProductAnalytics|An analytics provider has been successfully created, but it has not received any events yet. To continue with the setup, instrument your application and start sending events."
msgstr ""
msgid "ProductAnalytics|An error occurred while fetching data. Refresh the page to try again."
msgstr ""
@ -39361,6 +39373,9 @@ msgstr ""
msgid "ProductAnalytics|Contact our sales team"
msgstr ""
msgid "ProductAnalytics|Continue set up"
msgstr ""
msgid "ProductAnalytics|Creating your product analytics instance..."
msgstr ""
@ -39553,6 +39568,9 @@ msgstr ""
msgid "ProductAnalytics|The sender of tracking events"
msgstr ""
msgid "ProductAnalytics|The system is creating your analytics provider. In the meantime, you can instrument your application."
msgstr ""
msgid "ProductAnalytics|Then, return to this page and continue with the setup."
msgstr ""
@ -40390,9 +40408,39 @@ msgstr ""
msgid "ProjectMaintenance| To ensure that a full backup is available in case changes need to be restored, you should make an %{docs_link_start}export of the project%{docs_link_end}."
msgstr ""
msgid "ProjectMaintenance|Blob IDs to remove"
msgstr ""
msgid "ProjectMaintenance|Cancel"
msgstr ""
msgid "ProjectMaintenance|Enter a list of object IDs to be removed to reduce repository size."
msgstr ""
msgid "ProjectMaintenance|Enter multiple entries on separate lines."
msgstr ""
msgid "ProjectMaintenance|Housekeeping will need to be triggered manually afterwards to remove old versions of the file."
msgstr ""
msgid "ProjectMaintenance|How do I get a list of object IDs?"
msgstr ""
msgid "ProjectMaintenance|Manage repository storage and cleanup."
msgstr ""
msgid "ProjectMaintenance|Provide a list of blob object IDs to be removed."
msgstr ""
msgid "ProjectMaintenance|Remove blobs"
msgstr ""
msgid "ProjectMaintenance|Removing blobs by ID cannot be undone. Are you sure you want to continue?"
msgstr ""
msgid "ProjectMaintenance|Yes, remove blobs"
msgstr ""
msgid "ProjectOverview|Create new fork"
msgstr ""
@ -46305,6 +46353,12 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
msgid "Secret push protection"
msgstr ""
msgid "Secret push protection skipped via"
msgstr ""
msgid "Secret token"
msgstr ""
@ -46317,10 +46371,10 @@ msgstr ""
msgid "SecretDetection|Only a project maintainer or owner can toggle this feature."
msgstr ""
msgid "SecretDetection|Pre-receive Secret Detection is disabled"
msgid "SecretDetection|Secret push protection is disabled"
msgstr ""
msgid "SecretDetection|Pre-receive Secret Detection is enabled"
msgid "SecretDetection|Secret push protection is enabled"
msgstr ""
msgid "SecretDetection|This comment appears to have a token in it. Are you sure you want to add it?"
@ -46638,7 +46692,7 @@ msgstr ""
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
msgid "SecurityConfiguration|Toggle Pre-receive secret detection"
msgid "SecurityConfiguration|Toggle secret push protection"
msgstr ""
msgid "SecurityConfiguration|Upgrade or start a free trial"
@ -51594,6 +51648,9 @@ msgstr ""
msgid "Target branch: %{target_branch}"
msgstr ""
msgid "Target branches"
msgstr ""
msgid "Target project"
msgstr ""
@ -56461,7 +56518,7 @@ msgstr ""
msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
msgstr ""
msgid "User caps is enabled for this group, visit the %{pending_members_link_start}pending members%{pending_members_link_end} page to manage them."
msgid "User caps is enabled for this group. You can manage members on the %{pending_members_link_start}pending members%{pending_members_link_end} page."
msgstr ""
msgid "User created at"
@ -59897,7 +59954,10 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
msgid "You cannot add any more epics. This epic already has maximum number of child epics."
msgid "You cannot add any more epics. This epic already has maximum number of child issues & epics."
msgstr ""
msgid "You cannot add any more issues. This epic already has maximum number of child issues & epics."
msgstr ""
msgid "You cannot approve your own deployment. This configuration can be adjusted in the protected environment settings."
@ -61082,6 +61142,9 @@ msgstr ""
msgid "cannot be enabled until identity verification is completed"
msgstr ""
msgid "cannot be linked to the epic. This epic already has maximum number of child issues & epics."
msgstr ""
msgid "cannot be used because it belongs to a compromised private key. Stop using this key and generate a new one."
msgstr ""

View File

@ -63,7 +63,7 @@
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/fonts": "^1.3.0",
"@gitlab/svgs": "3.99.0",
"@gitlab/ui": "80.12.0",
"@gitlab/ui": "80.13.1",
"@gitlab/web-ide": "^0.0.1-dev-20240524043623",
"@mattiasbuelens/web-streams-adapter": "^0.1.0",
"@rails/actioncable": "7.0.8-1",

View File

@ -32,8 +32,6 @@ module Gitlab
span :project_containers_registry_size
# Pending members
button :view_pending_approvals, text: /View pending approvals/
div :pending_members_alert
div :pending_members
button :approve_member
button :confirm_member_approval, text: /^OK$/

View File

@ -26,5 +26,9 @@ FactoryBot.define do
trait :timeout do
status { 3 }
end
trait :with_configuration do
configuration { association(:bulk_import_configuration, bulk_import: instance) }
end
end
end

View File

@ -2,7 +2,7 @@
FactoryBot.define do
factory :bulk_import_configuration, class: 'BulkImports::Configuration' do
association :bulk_import, factory: :bulk_import
bulk_import
url { 'https://gitlab.example' }
access_token { 'token' }

View File

@ -89,17 +89,6 @@ RSpec.describe 'Admin updates settings', feature_category: :shared do
expect(page).to have_content 'Application settings saved successfully'
end
context 'when `export_audit_events` flag is disabled' do
before do
stub_feature_flags(export_audit_events: false)
visit general_admin_application_settings_path
end
it 'does not display the silent admin exports setting' do
expect(page).not_to have_selector('[data-testid="silent-admin-exports"]')
end
end
it 'change Keys settings' do
within_testid('admin-visibility-access-settings') do
select 'Are forbidden', from: 'RSA SSH keys'

View File

@ -40,6 +40,13 @@ RSpec.describe 'Projects > Settings > Repository settings', feature_category: :s
end
end
context 'Repository maintenance', :js do
it 'does not render remove blobs section' do
visit project_settings_repository_path(project)
expect(page).not_to have_content('Remove blobs')
end
end
context 'Branch rules', :js do
it 'renders branch rules settings' do
visit project_settings_repository_path(project)
@ -345,5 +352,13 @@ RSpec.describe 'Projects > Settings > Repository settings', feature_category: :s
include_examples 'shows mirror settings'
end
context 'Repository maintenance', :enable_admin_mode do
let(:mirror_available) { false }
it 'renders remove blobs section' do
expect(page).to have_content('Remove blobs')
end
end
end
end

View File

@ -22,10 +22,13 @@ describe('IDE review mode', () => {
store.state.currentProjectId = 'abcproject';
store.state.currentBranchId = 'main';
store.state.projects.abcproject = { ...projectData };
Vue.set(store.state.trees, 'abcproject/main', {
tree: [file('fileName')],
loading: false,
});
store.state.trees = {
...store.state.trees,
'abcproject/main': {
tree: [file('fileName')],
loading: false,
},
};
dispatch = jest.spyOn(store, 'dispatch');

View File

@ -1,6 +1,5 @@
import { GlSkeletonLoader } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import IdeTreeList from '~/ide/components/ide_tree_list.vue';
import { createStore } from '~/ide/stores';
import FileTree from '~/vue_shared/components/file_tree.vue';
@ -15,7 +14,10 @@ describe('IdeTreeList component', () => {
store.state.currentProjectId = 'abcproject';
store.state.currentBranchId = 'main';
store.state.projects.abcproject = { ...projectData };
Vue.set(store.state.trees, 'abcproject/main', { tree, loading });
store.state.trees = {
...store.state.trees,
'abcproject/main': { tree, loading },
};
wrapper = shallowMount(IdeTreeList, {
propsData: {

View File

@ -0,0 +1,98 @@
import { nextTick } from 'vue';
import { GlDrawer, GlFormTextarea, GlModal } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { getContentWrapperHeight } from '~/lib/utils/dom_utils';
import { DRAWER_Z_INDEX } from '~/lib/utils/constants';
import RemoveBlobs from '~/projects/settings/repository/maintenance/remove_blobs.vue';
jest.mock('~/lib/utils/dom_utils');
const TEST_HEADER_HEIGHT = '123px';
describe('Remove blobs', () => {
let wrapper;
const createComponent = () => {
getContentWrapperHeight.mockReturnValue(TEST_HEADER_HEIGHT);
wrapper = shallowMountExtended(RemoveBlobs);
};
const findDrawerTrigger = () => wrapper.findByTestId('drawer-trigger');
const findDrawer = () => wrapper.findComponent(GlDrawer);
const findModal = () => wrapper.findComponent(GlModal);
const removeBlobsButton = () => wrapper.findByTestId('remove-blobs');
const findTextarea = () => wrapper.findComponent(GlFormTextarea);
beforeEach(() => createComponent());
describe('initial state', () => {
it('renders a button to open the drawer', () => {
expect(findDrawerTrigger().exists()).toBe(true);
});
it('renders a drawer, closed by default', () => {
expect(findDrawer().props()).toMatchObject({
headerHeight: TEST_HEADER_HEIGHT,
zIndex: DRAWER_Z_INDEX,
open: false,
});
expect(findDrawer().text()).toContain(
'Enter a list of object IDs to be removed to reduce repository size.',
);
});
it('renders a modal, closed by default', () => {
expect(findModal().props()).toMatchObject({
visible: false,
title: 'Remove blobs',
modalId: 'remove-blobs-confirmation-modal',
actionCancel: { text: 'Cancel' },
actionPrimary: { text: 'Yes, remove blobs' },
});
expect(findModal().text()).toBe(
'Removing blobs by ID cannot be undone. Are you sure you want to continue?',
);
});
});
describe('removing blobs', () => {
beforeEach(() => findDrawerTrigger().vm.$emit('click'));
it('opens the drawer', () => {
expect(findDrawer().props('open')).toBe(true);
});
it('renders a text area without text', () => {
expect(findTextarea().text('disabled')).toBe('');
});
it('disables the primary action by default', () => {
expect(removeBlobsButton().props('disabled')).toBe(true);
});
describe('adding blob IDs', () => {
beforeEach(() => findTextarea().vm.$emit('input', '1234'));
it('enables the primary action when blob IDs are added', () => {
expect(removeBlobsButton().props('disabled')).toBe(false);
});
describe('confirmation modal', () => {
beforeEach(() => removeBlobsButton().vm.$emit('click'));
it('renders the confirmation modal when remove blobs button is clicked', () => {
expect(findModal().props('visible')).toBe(true);
});
it('closes the drawer when removal is confirmed', async () => {
findModal().vm.$emit('primary');
await nextTick();
expect(findDrawer().props('open')).toBe(false);
});
});
});
});
});

View File

@ -196,9 +196,9 @@ export const securityFeaturesMock = [
];
export const preReceiveSecretDetectionMock = {
name: 'Pre-receive Secret Detection',
name: 'Secret push protection',
description: `Block secrets such as keys and API tokens from being pushed to your repositories.
'Pre-receive secret detection is triggered when commits are pushed to a repository. ' \
'Secret push protection is triggered when commits are pushed to a repository. ' \
'If any secrets are detected, the push is blocked.`,
helpPath: SAST_HELP_PATH,
configurationHelpPath: helpPagePath(

View File

@ -47,12 +47,6 @@ RSpec.describe DiffHelper, feature_category: :code_review_workflow do
end
describe 'diff_options' do
let(:large_notebooks_enabled) { false }
before do
stub_feature_flags(large_ipynb_diffs: large_notebooks_enabled)
end
it 'returns no collapse false' do
expect(diff_options).to include(expanded: false)
end
@ -90,18 +84,8 @@ RSpec.describe DiffHelper, feature_category: :code_review_workflow do
allow(controller).to receive(:params) { { file_identifier: 'something.ipynb' } }
end
context 'when large_ipynb_diffs is disabled' do
it 'does not set max_patch_bytes_for_file_extension' do
expect(diff_options[:max_patch_bytes_for_file_extension]).to be_nil
end
end
context 'when large_ipynb_diffs is enabled' do
let(:large_notebooks_enabled) { true }
it 'sets max_patch_bytes_for_file_extension' do
expect(diff_options[:max_patch_bytes_for_file_extension]).to eq({ '.ipynb' => 1.megabyte })
end
it 'sets max_patch_bytes_for_file_extension' do
expect(diff_options[:max_patch_bytes_for_file_extension]).to eq({ '.ipynb' => 1.megabyte })
end
end
end

View File

@ -137,9 +137,9 @@ RSpec.describe ::Gitlab::Security::ScanConfiguration do
help_path: "/help/user/application_security/container_scanning/index",
configuration_help_path: "/help/user/application_security/container_scanning/index#configuration",
type: "container_scanning" }
:pre_receive_secret_detection | { name: _("Pre-receive Secret Detection"),
:pre_receive_secret_detection | { name: _("Secret push protection"),
description: "Block secrets such as keys and API tokens from being pushed to your repositories. " \
"Pre-receive secret detection is triggered when commits are pushed to a repository. " \
"Secret push protection is triggered when commits are pushed to a repository. " \
"If any secrets are detected, the push is blocked.",
help_path: Gitlab::Routing.url_helpers.help_page_path(
"user/application_security/secret_detection/pre_receive/index"),

View File

@ -37,14 +37,13 @@ RSpec.describe InitializerConnections do
expect { block_with_database_call }.not_to raise_error
end
it 'prevents any database connection if SKIP_RAISE_ON_INITIALIZE_CONNECTIONS is false',
quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/444962' do
it 'prevents any database connection if SKIP_RAISE_ON_INITIALIZE_CONNECTIONS is false' do
stub_env('SKIP_RAISE_ON_INITIALIZE_CONNECTIONS', 'false')
expect { block_with_database_call }.to raise_error(/Database connection should not be called during initializer/)
end
it 'restores original connection handler', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/444963' do
it 'restores original connection handler' do
original_handler = ActiveRecord::Base.connection_handler
expect { block_with_database_call }.to raise_error(/Database connection should not be called during initializer/)

Some files were not shown because too many files have changed in this diff Show More