Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-03-24 12:07:11 +00:00
parent a1384a9c4f
commit c7d68cbee7
74 changed files with 1144 additions and 283 deletions

View File

@ -11,7 +11,11 @@ import {
TOP_NAV_INVITE_MEMBERS_COMPONENT,
TRIGGER_ELEMENT_DISCLOSURE_DROPDOWN,
} from '~/invite_members/constants';
import { WORK_ITEM_TYPE_ENUM_EPIC, CREATE_NEW_WORK_ITEM_MODAL } from '~/work_items/constants';
import {
WORK_ITEM_TYPE_ENUM_EPIC,
CREATE_NEW_WORK_ITEM_MODAL,
CREATE_NEW_GROUP_WORK_ITEM_MODAL,
} from '~/work_items/constants';
import { DROPDOWN_Y_OFFSET, IMPERSONATING_OFFSET } from '../constants';
// Left offset required for the dropdown to be aligned with the super sidebar
@ -32,7 +36,7 @@ export default {
i18n: {
createNew: __('Create new…'),
},
inject: ['isImpersonating'],
inject: ['isImpersonating', 'fullPath', 'workItemPlanningViewEnabled'],
props: {
groups: {
type: Array,
@ -42,6 +46,7 @@ export default {
data() {
return {
dropdownOpen: false,
showCreateGroupWorkItemModal: false,
showCreateWorkItemModal: false,
};
},
@ -60,6 +65,16 @@ export default {
isCreateWorkItem(groupItem) {
return groupItem.component === CREATE_NEW_WORK_ITEM_MODAL;
},
isCreateGroupWorkItem(groupItem) {
return groupItem.component === CREATE_NEW_GROUP_WORK_ITEM_MODAL;
},
handleCreateWorkItemClick() {
if (this.workItemPlanningViewEnabled) {
this.showCreateWorkItemModal = true;
} else {
this.showCreateGroupWorkItemModal = true;
}
},
},
toggleId: 'create-menu-toggle',
TRIGGER_ELEMENT_DISCLOSURE_DROPDOWN,
@ -94,21 +109,38 @@ export default {
trigger-source="top_nav"
:trigger-element="$options.TRIGGER_ELEMENT_DISCLOSURE_DROPDOWN"
/>
<gl-disclosure-dropdown-item
v-else-if="isCreateGroupWorkItem(groupItem)"
:key="`${groupItem.text}-group-modal-trigger`"
:item="groupItem"
data-testid="new-group-work-item-trigger"
@action="showCreateGroupWorkItemModal = true"
/>
<gl-disclosure-dropdown-item
v-else-if="isCreateWorkItem(groupItem)"
:key="`${groupItem.text}-modal-trigger`"
:item="groupItem"
@action="showCreateWorkItemModal = true"
data-testid="new-work-item-trigger"
@action="handleCreateWorkItemClick"
/>
<gl-disclosure-dropdown-item v-else :key="groupItem.text" :item="groupItem" />
</template>
</gl-disclosure-dropdown-group>
<create-work-item-modal
v-if="showCreateWorkItemModal"
v-if="showCreateGroupWorkItemModal"
visible
hide-button
is-group
data-testid="new-group-work-item-modal"
:work-item-type-name="$options.WORK_ITEM_TYPE_ENUM_EPIC"
@hideModal="showCreateGroupWorkItemModal = false"
/>
<create-work-item-modal
v-if="showCreateWorkItemModal"
visible
hide-button
data-testid="new-work-item-modal"
:full-path="fullPath"
@hideModal="showCreateWorkItemModal = false"
/>
</gl-disclosure-dropdown>

View File

@ -141,11 +141,17 @@ export const initSuperSidebar = ({
projectBlobPath,
projectsPath,
groupsPath,
groupPath: groupsPath,
fullPath: sidebarData.work_items?.full_path,
hasIssuableHealthStatusFeature: sidebarData.work_items?.has_issuable_health_status_feature,
hasIssueWeightsFeature: sidebarData.work_items?.has_issue_weights_feature,
hasIterationsFeature: sidebarData.work_items?.has_iterations_feature,
issuesListPath: sidebarData.work_items?.issues_list_path,
canAdminLabel: parseBoolean(sidebarData.work_items?.can_admin_label),
labelsManagePath: sidebarData.work_items?.labels_manage_path,
workItemPlanningViewEnabled: parseBoolean(
sidebarData.work_items?.work_item_planning_view_enabled,
),
isGroup,
isSaas: parseBoolean(isSaas),
},

View File

@ -74,7 +74,7 @@ export const TOKEN_TITLE_GROUP_INVITE = __('Group invite');
export const TOKEN_TITLE_LABEL = __('Label');
export const TOKEN_TITLE_PROJECT = __('Project');
export const TOKEN_TITLE_MILESTONE = __('Milestone');
export const TOKEN_TITLE_MY_REACTION = __('My-Reaction');
export const TOKEN_TITLE_MY_REACTION = __('My reaction');
export const TOKEN_TITLE_ORGANIZATION = s__('Crm|Organization');
export const TOKEN_TITLE_RELEASE = __('Release');
export const TOKEN_TITLE_REVIEWER = s__('SearchToken|Reviewer');

View File

@ -256,6 +256,7 @@ export const DEFAULT_EPIC_COLORS = '#1068bf';
export const MAX_FREQUENT_PROJECTS = 3;
export const CREATE_NEW_WORK_ITEM_MODAL = 'create_new_work_item_modal';
export const CREATE_NEW_GROUP_WORK_ITEM_MODAL = 'create_new_group_work_item_modal';
export const RELATED_ITEM_ID_URL_QUERY_PARAM = 'related_item_id';
export const WORK_ITEM_REFERENCE_CHAR = '#';

View File

@ -56,6 +56,22 @@ module Nav
)
end
if can?(current_user, :create_work_item, group) && ::Feature.enabled?(:work_item_planning_view, group)
menu_items.push(
::Gitlab::Nav::TopNavMenuItem.build(
id: 'new_group_work_item',
title: _('New work item'),
component: 'create_new_group_work_item_modal',
data: {
track_action: 'click_link_new_group_work_item',
track_label: 'plus_menu_dropdown',
track_property: 'navigation_top',
testid: 'new_group_work_item_button'
}
)
)
end
menu_items.push(create_epic_menu_item(group))
if can?(current_user, :admin_group_member, group)
@ -73,19 +89,35 @@ module Nav
merge_project = merge_request_source_project_for_project(project)
if show_new_issue_link?(project)
menu_items.push(
::Gitlab::Nav::TopNavMenuItem.build(
id: 'new_issue',
title: _('New issue'),
href: new_project_issue_path(project),
data: {
track_action: 'click_link_new_issue',
track_label: 'plus_menu_dropdown',
track_property: 'navigation_top',
testid: 'new_issue_link'
}
if ::Feature.enabled?(:work_item_planning_view, project.group)
menu_items.push(
::Gitlab::Nav::TopNavMenuItem.build(
id: 'new_work_item',
title: _('New work item'),
component: 'create_new_work_item_modal',
data: {
track_action: 'click_link_new_work_item',
track_label: 'plus_menu_dropdown',
track_property: 'navigation_top',
testid: 'new_work_item_button'
}
)
)
)
else
menu_items.push(
::Gitlab::Nav::TopNavMenuItem.build(
id: 'new_issue',
title: _('New issue'),
href: new_project_issue_path(project),
data: {
track_action: 'click_link_new_issue',
track_label: 'plus_menu_dropdown',
track_property: 'navigation_top',
testid: 'new_issue_link'
}
)
)
end
end
if merge_project

View File

@ -111,7 +111,7 @@ module SidebarsHelper
stop_impersonation_path: admin_impersonation_path,
shortcut_links: shortcut_links(user: user, project: project),
track_visits_path: track_namespace_visits_path,
work_items: work_items_modal_data(group)
work_items: work_items_modal_data(group, project)
})
end
@ -133,7 +133,20 @@ module SidebarsHelper
}
end
def work_items_modal_data(group)
def work_items_modal_data(group, project)
if project&.persisted?
return {
full_path: project.full_path,
has_issuable_health_status_feature: project.licensed_feature_available?(:issuable_health_status).to_s,
issues_list_path: project_issues_path(project),
labels_manage_path: project_labels_path(project),
can_admin_label: can?(current_user, :admin_label, project).to_s,
has_issue_weights_feature: project.licensed_feature_available?(:issue_weights).to_s,
has_iterations_feature: project.licensed_feature_available?(:iterations).to_s,
work_item_planning_view_enabled: ::Feature.enabled?(:work_item_planning_view, project.group).to_s
}
end
return unless group && group.id
{
@ -141,7 +154,9 @@ module SidebarsHelper
has_issuable_health_status_feature: group.licensed_feature_available?(:issuable_health_status).to_s,
issues_list_path: issues_group_path(group),
labels_manage_path: group_labels_path(group),
can_admin_label: can?(current_user, :admin_label, group).to_s
can_admin_label: can?(current_user, :admin_label, group).to_s,
has_issue_weights_feature: group.licensed_feature_available?(:issue_weights).to_s,
work_item_planning_view_enabled: ::Feature.enabled?(:work_item_planning_view, group).to_s
}
end

View File

@ -0,0 +1,9 @@
---
name: ci_glab_for_release
feature_issue_url: https://gitlab.com/gitlab-org/cli/-/issues/7450
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/185109
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/524346
milestone: '17.11'
group: group::pipeline authoring
type: beta
default_enabled: false

View File

@ -1,9 +0,0 @@
---
name: zoekt_reduced_pull_frequency
feature_issue_url:
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/160575
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/474248
milestone: '17.3'
group: group::global search
type: ops
default_enabled: true

View File

@ -211,17 +211,11 @@ clusters_managed_resources:
- table: p_ci_builds
column: build_id
on_delete: async_delete
- table: ci_builds
column: build_id
on_delete: async_delete
country_access_logs:
- table: users
column: user_id
on_delete: async_delete
dast_pre_scan_verifications:
- table: ci_pipelines
column: ci_pipeline_id
on_delete: async_delete
- table: p_ci_pipelines
column: ci_pipeline_id
on_delete: async_delete
@ -240,9 +234,6 @@ dast_profiles:
column: project_id
on_delete: async_delete
dast_profiles_pipelines:
- table: ci_pipelines
column: ci_pipeline_id
on_delete: async_delete
- table: p_ci_pipelines
column: ci_pipeline_id
on_delete: async_delete
@ -258,9 +249,6 @@ dast_scanner_profiles:
column: project_id
on_delete: async_delete
dast_scanner_profiles_builds:
- table: ci_builds
column: ci_build_id
on_delete: async_delete
- table: p_ci_builds
column: ci_build_id
on_delete: async_delete
@ -273,9 +261,6 @@ dast_site_profiles:
column: project_id
on_delete: async_delete
dast_site_profiles_builds:
- table: ci_builds
column: ci_build_id
on_delete: async_delete
- table: p_ci_builds
column: ci_build_id
on_delete: async_delete
@ -296,9 +281,6 @@ dependency_list_export_parts:
column: organization_id
on_delete: async_delete
dependency_list_exports:
- table: ci_pipelines
column: pipeline_id
on_delete: async_delete
- table: p_ci_pipelines
column: pipeline_id
on_delete: async_delete
@ -364,9 +346,6 @@ members:
column: user_id
on_delete: async_delete
merge_request_metrics:
- table: ci_pipelines
column: pipeline_id
on_delete: async_nullify
- table: p_ci_pipelines
column: pipeline_id
on_delete: async_nullify
@ -381,23 +360,14 @@ merge_request_requested_changes:
column: user_id
on_delete: async_delete
merge_requests:
- table: ci_pipelines
column: head_pipeline_id
on_delete: async_nullify
- table: p_ci_pipelines
column: head_pipeline_id
on_delete: async_nullify
merge_trains:
- table: ci_pipelines
column: pipeline_id
on_delete: async_nullify
- table: p_ci_pipelines
column: pipeline_id
on_delete: async_nullify
ml_candidates:
- table: ci_builds
column: ci_build_id
on_delete: async_nullify
- table: p_ci_builds
column: ci_build_id
on_delete: async_nullify
@ -491,9 +461,6 @@ p_ci_stages:
column: project_id
on_delete: async_delete
packages_build_infos:
- table: ci_pipelines
column: pipeline_id
on_delete: async_nullify
- table: p_ci_pipelines
column: pipeline_id
on_delete: async_nullify
@ -504,16 +471,10 @@ packages_npm_metadata_caches:
target_column: status
target_value: 2
packages_package_file_build_infos:
- table: ci_pipelines
column: pipeline_id
on_delete: async_nullify
- table: p_ci_pipelines
column: pipeline_id
on_delete: async_nullify
pages_deployments:
- table: ci_builds
column: ci_build_id
on_delete: async_nullify
- table: p_ci_builds
column: ci_build_id
on_delete: async_nullify
@ -556,9 +517,6 @@ push_rules:
column: organization_id
on_delete: async_delete
requirements_management_test_reports:
- table: ci_builds
column: build_id
on_delete: async_nullify
- table: p_ci_builds
column: build_id
on_delete: async_nullify
@ -571,9 +529,6 @@ sbom_components:
column: organization_id
on_delete: async_delete
sbom_occurrences:
- table: ci_pipelines
column: pipeline_id
on_delete: async_nullify
- table: p_ci_pipelines
column: pipeline_id
on_delete: async_nullify
@ -593,9 +548,6 @@ sbom_sources:
column: organization_id
on_delete: async_delete
security_scans:
- table: ci_builds
column: build_id
on_delete: async_delete
- table: p_ci_builds
column: build_id
on_delete: async_delete
@ -611,9 +563,6 @@ snippets:
column: organization_id
on_delete: async_delete
terraform_state_versions:
- table: ci_builds
column: ci_build_id
on_delete: async_nullify
- table: p_ci_builds
column: ci_build_id
on_delete: async_nullify
@ -686,9 +635,6 @@ vulnerability_external_issue_links:
column: author_id
on_delete: async_delete
vulnerability_feedback:
- table: ci_pipelines
column: pipeline_id
on_delete: async_nullify
- table: p_ci_pipelines
column: pipeline_id
on_delete: async_nullify
@ -754,12 +700,6 @@ vulnerability_namespace_statistics:
column: namespace_id
on_delete: async_delete
vulnerability_occurrences:
- table: ci_pipelines
column: initial_pipeline_id
on_delete: async_nullify
- table: ci_pipelines
column: latest_pipeline_id
on_delete: async_nullify
- table: p_ci_pipelines
column: initial_pipeline_id
on_delete: async_nullify
@ -803,9 +743,6 @@ vulnerability_state_transitions:
column: author_id
on_delete: async_nullify
vulnerability_statistics:
- table: ci_pipelines
column: latest_pipeline_id
on_delete: async_nullify
- table: p_ci_pipelines
column: latest_pipeline_id
on_delete: async_nullify

View File

@ -879,6 +879,9 @@ Gitlab.ee do
Settings.cron_jobs['iterations_generator_worker'] ||= {}
Settings.cron_jobs['iterations_generator_worker']['cron'] ||= '5 0 * * *'
Settings.cron_jobs['iterations_generator_worker']['job_class'] = 'Iterations::Cadences::ScheduleCreateIterationsWorker'
Settings.cron_jobs['vulnerability_archival_schedule_worker'] ||= {}
Settings.cron_jobs['vulnerability_archival_schedule_worker']['cron'] ||= '0 0 1 * *'
Settings.cron_jobs['vulnerability_archival_schedule_worker']['job_class'] = 'Vulnerabilities::Archival::ScheduleWorker'
Settings.cron_jobs['vulnerability_statistics_schedule_worker'] ||= {}
Settings.cron_jobs['vulnerability_statistics_schedule_worker']['cron'] ||= '15 1,20 * * *'
Settings.cron_jobs['vulnerability_statistics_schedule_worker']['job_class'] = 'Vulnerabilities::Statistics::ScheduleWorker'

View File

@ -0,0 +1,8 @@
---
migration_job_name: BackfillPackagesConanFileMetadataProjectId
description: Backfills sharding key `packages_conan_file_metadata.project_id` from `packages_package_files`.
feature_category: package_registry
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/185222
milestone: '17.11'
queued_migration_version: 20250320085452
finalized_by: # version of the migration that finalized this BBM

View File

@ -0,0 +1,8 @@
---
migration_job_name: BackfillPackagesDebianFileMetadataProjectId
description: Backfills sharding key `packages_debian_file_metadata.project_id` from `packages_package_files`.
feature_category: package_registry
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/185223
milestone: '17.11'
queued_migration_version: 20250320085933
finalized_by: # version of the migration that finalized this BBM

View File

@ -18,3 +18,4 @@ desired_sharding_key:
sharding_key: project_id
belongs_to: package_file
table_size: small
desired_sharding_key_migration_job_name: BackfillPackagesConanFileMetadataProjectId

View File

@ -18,3 +18,4 @@ desired_sharding_key:
sharding_key: project_id
belongs_to: package_file
table_size: small
desired_sharding_key_migration_job_name: BackfillPackagesDebianFileMetadataProjectId

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
class AddProjectIdToPackagesConanFileMetadata < Gitlab::Database::Migration[2.2]
milestone '17.11'
def change
add_column :packages_conan_file_metadata, :project_id, :bigint
end
end

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
class AddProjectIdToPackagesDebianFileMetadata < Gitlab::Database::Migration[2.2]
milestone '17.11'
def change
add_column :packages_debian_file_metadata, :project_id, :bigint
end
end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class IndexPackagesConanFileMetadataOnProjectId < Gitlab::Database::Migration[2.2]
milestone '17.11'
disable_ddl_transaction!
INDEX_NAME = 'index_packages_conan_file_metadata_on_project_id'
def up
add_concurrent_index :packages_conan_file_metadata, :project_id, name: INDEX_NAME
end
def down
remove_concurrent_index_by_name :packages_conan_file_metadata, INDEX_NAME
end
end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class AddPackagesConanFileMetadataProjectIdFk < Gitlab::Database::Migration[2.2]
milestone '17.11'
disable_ddl_transaction!
def up
add_concurrent_foreign_key :packages_conan_file_metadata, :projects, column: :project_id, on_delete: :cascade
end
def down
with_lock_retries do
remove_foreign_key :packages_conan_file_metadata, column: :project_id
end
end
end

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
class AddPackagesConanFileMetadataProjectIdTrigger < Gitlab::Database::Migration[2.2]
milestone '17.11'
def up
install_sharding_key_assignment_trigger(
table: :packages_conan_file_metadata,
sharding_key: :project_id,
parent_table: :packages_package_files,
parent_sharding_key: :project_id,
foreign_key: :package_file_id
)
end
def down
remove_sharding_key_assignment_trigger(
table: :packages_conan_file_metadata,
sharding_key: :project_id,
parent_table: :packages_package_files,
parent_sharding_key: :project_id,
foreign_key: :package_file_id
)
end
end

View File

@ -0,0 +1,40 @@
# frozen_string_literal: true
class QueueBackfillPackagesConanFileMetadataProjectId < Gitlab::Database::Migration[2.2]
milestone '17.11'
restrict_gitlab_migration gitlab_schema: :gitlab_main_cell
MIGRATION = "BackfillPackagesConanFileMetadataProjectId"
DELAY_INTERVAL = 2.minutes
BATCH_SIZE = 1000
SUB_BATCH_SIZE = 100
def up
queue_batched_background_migration(
MIGRATION,
:packages_conan_file_metadata,
:id,
:project_id,
:packages_package_files,
:project_id,
:package_file_id,
job_interval: DELAY_INTERVAL,
batch_size: BATCH_SIZE,
sub_batch_size: SUB_BATCH_SIZE
)
end
def down
delete_batched_background_migration(
MIGRATION,
:packages_conan_file_metadata,
:id,
[
:project_id,
:packages_package_files,
:project_id,
:package_file_id
]
)
end
end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class IndexPackagesDebianFileMetadataOnProjectId < Gitlab::Database::Migration[2.2]
milestone '17.11'
disable_ddl_transaction!
INDEX_NAME = 'index_packages_debian_file_metadata_on_project_id'
def up
add_concurrent_index :packages_debian_file_metadata, :project_id, name: INDEX_NAME
end
def down
remove_concurrent_index_by_name :packages_debian_file_metadata, INDEX_NAME
end
end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class AddPackagesDebianFileMetadataProjectIdFk < Gitlab::Database::Migration[2.2]
milestone '17.11'
disable_ddl_transaction!
def up
add_concurrent_foreign_key :packages_debian_file_metadata, :projects, column: :project_id, on_delete: :cascade
end
def down
with_lock_retries do
remove_foreign_key :packages_debian_file_metadata, column: :project_id
end
end
end

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
class AddPackagesDebianFileMetadataProjectIdTrigger < Gitlab::Database::Migration[2.2]
milestone '17.11'
def up
install_sharding_key_assignment_trigger(
table: :packages_debian_file_metadata,
sharding_key: :project_id,
parent_table: :packages_package_files,
parent_sharding_key: :project_id,
foreign_key: :package_file_id
)
end
def down
remove_sharding_key_assignment_trigger(
table: :packages_debian_file_metadata,
sharding_key: :project_id,
parent_table: :packages_package_files,
parent_sharding_key: :project_id,
foreign_key: :package_file_id
)
end
end

View File

@ -0,0 +1,40 @@
# frozen_string_literal: true
class QueueBackfillPackagesDebianFileMetadataProjectId < Gitlab::Database::Migration[2.2]
milestone '17.11'
restrict_gitlab_migration gitlab_schema: :gitlab_main_cell
MIGRATION = "BackfillPackagesDebianFileMetadataProjectId"
DELAY_INTERVAL = 2.minutes
BATCH_SIZE = 1000
SUB_BATCH_SIZE = 100
def up
queue_batched_background_migration(
MIGRATION,
:packages_debian_file_metadata,
:package_file_id,
:project_id,
:packages_package_files,
:project_id,
:package_file_id,
job_interval: DELAY_INTERVAL,
batch_size: BATCH_SIZE,
sub_batch_size: SUB_BATCH_SIZE
)
end
def down
delete_batched_background_migration(
MIGRATION,
:packages_debian_file_metadata,
:package_file_id,
[
:project_id,
:packages_package_files,
:project_id,
:package_file_id
]
)
end
end

View File

@ -0,0 +1 @@
6720c41831aee47380b8a7bfa83f1d3e61d73fb4f93f87d74e231534b50a897d

View File

@ -0,0 +1 @@
be35fa15e3dd3baba7bce0c45b295030a7743836a18fe2bf1770ecd281e6466b

View File

@ -0,0 +1 @@
248df833e5ca809fb315368a6aea8d86f4a853b226fa371e95b399653209f174

View File

@ -0,0 +1 @@
a1b96646a07be6c331dd8a58b921c2ca1ca123fb324db000c97752fbe5e94a6a

View File

@ -0,0 +1 @@
3bf6398499bcd35cd892af37b66aadf75c86515313db07718f9191feba4aee6e

View File

@ -0,0 +1 @@
c110adc24435dcae929fb05418f00e4ef6bfce14545078a2a43445777ad298ba

View File

@ -0,0 +1 @@
e6175b08a9c6528ae9a88c0187aabf3190a9f9270b9682b2253f5051914580c0

View File

@ -0,0 +1 @@
4fb2f62a71ffaf9ff219dcab1071b28f6ba4f405039365e39494abeb806dfdaf

View File

@ -0,0 +1 @@
955191ee0d02bb2ba449cf57317f4a0f950f058bf96affc7ade0ce9c120f854b

View File

@ -0,0 +1 @@
b069bbd4e314a2eab14e1c56361686e38576bb1514cee2e5659fff9e13cee4ed

View File

@ -1551,6 +1551,22 @@ RETURN NEW;
END
$$;
CREATE FUNCTION trigger_218433b4faa5() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
IF NEW."project_id" IS NULL THEN
SELECT "project_id"
INTO NEW."project_id"
FROM "packages_package_files"
WHERE "packages_package_files"."id" = NEW."package_file_id";
END IF;
RETURN NEW;
END
$$;
CREATE FUNCTION trigger_219952df8fc4() RETURNS trigger
LANGUAGE plpgsql
AS $$
@ -2798,6 +2814,22 @@ RETURN NEW;
END
$$;
CREATE FUNCTION trigger_81b53b626109() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
IF NEW."project_id" IS NULL THEN
SELECT "project_id"
INTO NEW."project_id"
FROM "packages_package_files"
WHERE "packages_package_files"."id" = NEW."package_file_id";
END IF;
RETURN NEW;
END
$$;
CREATE FUNCTION trigger_8204480b3a2e() RETURNS trigger
LANGUAGE plpgsql
AS $$
@ -18630,6 +18662,7 @@ CREATE TABLE packages_conan_file_metadata (
recipe_revision_id bigint,
package_revision_id bigint,
package_reference_id bigint,
project_id bigint,
CONSTRAINT check_conan_file_metadata_ref_null_for_recipe_files CHECK ((NOT ((conan_file_type = 1) AND (package_reference_id IS NOT NULL))))
);
@ -18728,6 +18761,7 @@ CREATE TABLE packages_debian_file_metadata (
component text,
architecture text,
fields jsonb,
project_id bigint,
CONSTRAINT check_2ebedda4b6 CHECK ((char_length(component) <= 255)),
CONSTRAINT check_e6e1fffcca CHECK ((char_length(architecture) <= 255))
);
@ -35878,6 +35912,8 @@ CREATE INDEX index_packages_conan_file_metadata_on_package_reference_id ON packa
CREATE INDEX index_packages_conan_file_metadata_on_package_revision_id ON packages_conan_file_metadata USING btree (package_revision_id);
CREATE INDEX index_packages_conan_file_metadata_on_project_id ON packages_conan_file_metadata USING btree (project_id);
CREATE INDEX index_packages_conan_file_metadata_on_recipe_revision_id ON packages_conan_file_metadata USING btree (recipe_revision_id);
CREATE UNIQUE INDEX index_packages_conan_metadata_on_package_id_username_channel ON packages_conan_metadata USING btree (package_id, package_username, package_channel);
@ -35894,6 +35930,8 @@ CREATE INDEX index_packages_conan_package_revisions_on_project_id ON packages_co
CREATE INDEX index_packages_conan_recipe_revisions_on_project_id ON packages_conan_recipe_revisions USING btree (project_id);
CREATE INDEX index_packages_debian_file_metadata_on_project_id ON packages_debian_file_metadata USING btree (project_id);
CREATE INDEX index_packages_debian_group_architectures_on_group_id ON packages_debian_group_architectures USING btree (group_id);
CREATE INDEX index_packages_debian_group_component_files_on_component_id ON packages_debian_group_component_files USING btree (component_id);
@ -40766,6 +40804,8 @@ CREATE TRIGGER trigger_206cbe2dc1a2 BEFORE INSERT OR UPDATE ON packages_package_
CREATE TRIGGER trigger_207005e8e995 BEFORE INSERT OR UPDATE ON operations_strategies FOR EACH ROW EXECUTE FUNCTION trigger_207005e8e995();
CREATE TRIGGER trigger_218433b4faa5 BEFORE INSERT OR UPDATE ON packages_conan_file_metadata FOR EACH ROW EXECUTE FUNCTION trigger_218433b4faa5();
CREATE TRIGGER trigger_219952df8fc4 BEFORE INSERT OR UPDATE ON merge_request_blocks FOR EACH ROW EXECUTE FUNCTION trigger_219952df8fc4();
CREATE TRIGGER trigger_22262f5f16d8 BEFORE INSERT OR UPDATE ON issues FOR EACH ROW EXECUTE FUNCTION trigger_22262f5f16d8();
@ -40924,6 +40964,8 @@ CREATE TRIGGER trigger_80578cfbdaf9 BEFORE INSERT OR UPDATE ON push_event_payloa
CREATE TRIGGER trigger_81b4c93e7133 BEFORE INSERT OR UPDATE ON pages_deployment_states FOR EACH ROW EXECUTE FUNCTION trigger_81b4c93e7133();
CREATE TRIGGER trigger_81b53b626109 BEFORE INSERT OR UPDATE ON packages_debian_file_metadata FOR EACH ROW EXECUTE FUNCTION trigger_81b53b626109();
CREATE TRIGGER trigger_8204480b3a2e BEFORE INSERT OR UPDATE ON incident_management_escalation_rules FOR EACH ROW EXECUTE FUNCTION trigger_8204480b3a2e();
CREATE TRIGGER trigger_84d67ad63e93 BEFORE INSERT OR UPDATE ON wiki_page_slugs FOR EACH ROW EXECUTE FUNCTION trigger_84d67ad63e93();
@ -41572,6 +41614,9 @@ ALTER TABLE ONLY bulk_import_trackers
ALTER TABLE ONLY audit_events_instance_external_audit_event_destinations
ADD CONSTRAINT fk_2d3ebd0fbc FOREIGN KEY (stream_destination_id) REFERENCES audit_events_instance_external_streaming_destinations(id) ON DELETE SET NULL;
ALTER TABLE ONLY packages_conan_file_metadata
ADD CONSTRAINT fk_2e2815280f FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY work_item_type_user_preferences
ADD CONSTRAINT fk_2e37b4f066 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@ -41617,6 +41662,9 @@ ALTER TABLE ONLY lists
ALTER TABLE ONLY approvals
ADD CONSTRAINT fk_310d714958 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
ALTER TABLE ONLY packages_debian_file_metadata
ADD CONSTRAINT fk_31440cf2d5 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY namespaces
ADD CONSTRAINT fk_319256d87a FOREIGN KEY (file_template_project_id) REFERENCES projects(id) ON DELETE SET NULL;

View File

@ -96,7 +96,7 @@ The default prefix is `glpat-` but administrators can change it.
By default, [secret push protection](../../user/application_security/secret_detection/secret_push_protection/_index.md) and
[pipeline secret detection](../../user/application_security/secret_detection/pipeline/_index.md#detected-secrets) do not detect custom prefixes.
Custom prefixes might cause an increase in false positives.
Custom prefixes might cause an increase in false negatives.
### Set a prefix
@ -148,6 +148,10 @@ To set a custom token prefix:
1. In the **Instance token prefix** field, enter your custom prefix.
1. Select **Save changes**.
By default, [secret push protection](../../user/application_security/secret_detection/secret_push_protection/_index.md), [client-side secret detection](../../user/application_security/secret_detection/client/_index.md) and
[pipeline secret detection](../../user/application_security/secret_detection/pipeline/_index.md#detected-secrets) do not detect custom instance token prefixes.
Custom instance token prefixes might cause an increase in false negatives.
## Repository size limit
{{< details >}}

View File

@ -46,7 +46,7 @@ Predefined variables become available at three different phases of pipeline exec
| `CI_API_GRAPHQL_URL` | Pre-pipeline | The GitLab API GraphQL root URL. Introduced in GitLab 15.11. |
| `CI_BUILDS_DIR` | Job-only | The top-level directory where builds are executed. |
| `CI_COMMIT_AUTHOR` | Pre-pipeline | The author of the commit in `Name <email>` format. |
| `CI_COMMIT_BEFORE_SHA` | Pre-pipeline | The previous latest commit present on a branch or tag. Is always `0000000000000000000000000000000000000000` for merge request pipelines, the first commit in pipelines for branches or tags, or when manually running a pipeline. |
| `CI_COMMIT_BEFORE_SHA` | Pre-pipeline | The previous latest commit present on a branch or tag. Is always `0000000000000000000000000000000000000000` for merge request pipelines, scheduled pipelines, the first commit in pipelines for branches or tags, or when manually running a pipeline. |
| `CI_COMMIT_BRANCH` | Pre-pipeline | The commit branch name. Available in branch pipelines, including pipelines for the default branch. Not available in merge request pipelines or tag pipelines. |
| `CI_COMMIT_DESCRIPTION` | Pre-pipeline | The description of the commit. If the title is shorter than 100 characters, the message without the first line. |
| `CI_COMMIT_MESSAGE` | Pre-pipeline | The full commit message. |

View File

@ -2247,6 +2247,9 @@ from. The specified jobs must all be in earlier stages. You can also set a job t
When `dependencies` is not defined in a job, all jobs in earlier stages are considered dependent
and the job fetches all artifacts from those jobs.
To fetch artifacts from a job in the same stage, you must use [`needs:artifacts`](#needsartifacts).
You should not combine `dependencies` with `needs` in the same job.
**Keyword type**: Job keyword. You can use it only as part of a job.
**Supported values**:
@ -2301,8 +2304,6 @@ the [stage](#stages) precedence.
- The job status does not matter. If a job fails or it's a manual job that isn't triggered, no error occurs.
- If the artifacts of a dependent job are [expired](#artifactsexpire_in) or
[deleted](../jobs/job_artifacts.md#delete-job-log-and-artifacts), then the job fails.
- To fetch artifacts from a job in the same stage, you must use [`needs:artifacts`](#needsartifacts).
You should not combine `dependencies` with `needs` in the same job.
### `environment`

View File

@ -1546,9 +1546,9 @@ This sensitive data must be handled carefully to avoid leaks which could lead to
### At rest
- Credentials must be encrypted while at rest (database or file) with `encrypts`.
- Credentials must be stored as salted hashes, at rest, where the plaintext value itself does not need to be retrieved.
- When the intention is to only compare secrets, store only the salted hash of the secret instead of the encrypted value.
- Salted hashes should be used to store any sensitive value where the plaintext value itself does not need to be retrieved.
- If the plain text value of the credentials needs to be retrieved, those credentials must be encrypted at rest (database or file) with [`encrypts`](#examples-5).
- Never commit credentials to repositories.
- The [Gitleaks Git hook](https://gitlab.com/gitlab-com/gl-security/security-research/gitleaks-endpoint-installer) is recommended for preventing credentials from being committed.
- Never log credentials under any circumstance. Issue [#353857](https://gitlab.com/gitlab-org/gitlab/-/issues/353857) is an example of credential leaks through log file.
@ -1610,13 +1610,13 @@ class WebHookLog < ApplicationRecord
end
```
Using [the `TokenAuthenticatable` concern](token_authenticatable.md) to create a prefixed token:
Using [the `TokenAuthenticatable` concern](token_authenticatable.md) to create a prefixed token **and** store the hashed value of the token, at rest:
```ruby
class User
FEED_TOKEN_PREFIX = 'glft-'
add_authentication_token_field :feed_token, format_with_prefix: :prefix_for_feed_token
add_authentication_token_field :feed_token, digest: true, format_with_prefix: :prefix_for_feed_token
def prefix_for_feed_token
FEED_TOKEN_PREFIX

View File

@ -63,7 +63,7 @@ Prerequisites:
To install the GitLab for Jira Cloud app:
1. In Jira, on the top bar, select **Apps > Explore more apps** and search for `GitLab for Jira Cloud`.
1. In Jira, in the sidebar, select **Apps > Explore more apps** and search for `GitLab for Jira Cloud`.
1. Select **GitLab for Jira Cloud**, then select **Get it now**.
Alternatively, [get the app directly from the Atlassian Marketplace](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud?tab=overview&hosting=cloud).

View File

@ -1,5 +1,5 @@
---
redirect_to: ../../group/import/index.md
redirect_to: ../../group/import/_index.md
remove_date: "2025-01-25"
stage: Foundations
group: Import and Integrate

View File

@ -573,7 +573,7 @@ You can filter by the following:
- [Iteration](../group/iterations/_index.md)
- Label
- Milestone
- My Reaction
- My reaction
- Release
- Type (issue/incident)
- [Weight](issues/issue_weight.md)

View File

@ -513,10 +513,11 @@ This feature is built on top of Git tags, so virtually no extra data is needed b
The way of using the [`release` keyword](../../../ci/yaml/_index.md#release) is planned to change.
The `release-cli` tool is [being replaced](https://gitlab.com/groups/gitlab-org/-/epics/15437) by the [GitLab CLI tool](https://gitlab.com/gitlab-org/cli/).
You must use GitLab CLI tool `v1.53.0` or higher, or you could receive one of these error messages:
You must use GitLab CLI tool `v1.53.0` or higher, or you could receive one of these error messages or warnings:
- `Error: glab command not found. Please install glab v1.53.0 or higher.`
- `Error: Please use glab v1.53.0 or higher.`
- `Warning: release-cli will not be supported after 18.0. Please use glab version >= 1.53.0.`
There are two ways to have the GitLab CLI tool:

View File

@ -0,0 +1,10 @@
# frozen_string_literal: true
module Gitlab
module BackgroundMigration
class BackfillPackagesConanFileMetadataProjectId < BackfillDesiredShardingKeyJob
operation_name :backfill_packages_conan_file_metadata_project_id
feature_category :package_registry
end
end
end

View File

@ -0,0 +1,10 @@
# frozen_string_literal: true
module Gitlab
module BackgroundMigration
class BackfillPackagesDebianFileMetadataProjectId < BackfillDesiredShardingKeyJob
operation_name :backfill_packages_debian_file_metadata_project_id
feature_category :package_registry
end
end
end

View File

@ -4,44 +4,35 @@ module Gitlab
module Ci
module Build
class Releaser
CREATE_BASE_COMMAND = 'release-cli create'
CREATE_SINGLE_FLAGS = %i[name description tag_name tag_message ref released_at].freeze
CREATE_ARRAY_FLAGS = %i[milestones].freeze
include ::Gitlab::Utils::StrongMemoize
RELEASE_CLI_CREATE_BASE_COMMAND = 'release-cli create'
RELEASE_CLI_CREATE_SINGLE_FLAGS = %i[name description tag_name tag_message ref released_at].freeze
RELEASE_CLI_CREATE_ARRAY_FLAGS = %i[milestones].freeze
RELEASE_CLI_CATALOG_PUBLISH_FLAG = '--catalog-publish'
# If these versions or error messages are updated, the documentation should be updated as well.
RELEASE_CLI_REQUIRED_VERSION = '0.22.0'
TROUBLESHOOTING_URL = Rails.application.routes.url_helpers.help_page_url('user/project/releases/_index.md', anchor: 'gitlab-cli-version-requirement')
GLAB_REQUIRED_VERSION = '1.53.0'
TROUBLE_SHOOTING_URL = Rails.application.routes.url_helpers.help_page_url('user/project/releases/_index.md', anchor: 'gitlab-cli-version-requirement')
GLAB_WARNING_MESSAGE = "Warning: release-cli will not be supported after 18.0. Please use glab version >= #{GLAB_REQUIRED_VERSION}. Troubleshooting: #{TROUBLESHOOTING_URL}".freeze
GLAB_COMMAND_CHECK_COMMAND = <<~BASH.freeze
if ! command -v glab &> /dev/null; then
echo "Error: glab command not found. Please install glab #{GLAB_REQUIRED_VERSION} or higher. Troubleshooting: #{TROUBLE_SHOOTING_URL}"
exit 1
fi
BASH
GLAB_VERSION_CHECK_COMMAND = <<~BASH.freeze
if [ "$(printf "%s\n%s" "#{GLAB_REQUIRED_VERSION}" "$(glab --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')" | sort -V | head -n1)" = "#{GLAB_REQUIRED_VERSION}" ]; then
echo "Validating glab version. OK"
else
echo "Error: Please use glab #{GLAB_REQUIRED_VERSION} or higher. Troubleshooting: #{TROUBLE_SHOOTING_URL}"
exit 1
fi
BASH
GLAB_LOGIN_COMMAND = 'glab auth login --job-token $CI_JOB_TOKEN --hostname $CI_SERVER_FQDN --api-protocol $CI_SERVER_PROTOCOL'
GLAB_MAIN_COMMAND = 'GITLAB_HOST=$CI_SERVER_URL glab -R $CI_PROJECT_PATH'
GLAB_CREATE_COMMAND = "#{GLAB_MAIN_COMMAND} release create".freeze
GLAB_ENV_SET_UNIX = 'export GITLAB_HOST=$CI_SERVER_URL'
GLAB_ENV_SET_WINDOWS = '$env:GITLAB_HOST = $env:CI_SERVER_URL'
GLAB_LOGIN_UNIX = 'glab auth login --job-token $CI_JOB_TOKEN --hostname $CI_SERVER_FQDN --api-protocol $CI_SERVER_PROTOCOL'
GLAB_LOGIN_WINDOWS = 'glab auth login --job-token $env:CI_JOB_TOKEN --hostname $env:CI_SERVER_FQDN --api-protocol $env:CI_SERVER_PROTOCOL'
GLAB_CREATE_UNIX = 'glab -R $CI_PROJECT_PATH release create'
GLAB_CREATE_WINDOWS = 'glab -R $env:CI_PROJECT_PATH release create'
GLAB_PUBLISH_TO_CATALOG_FLAG = '--publish-to-catalog' # enables publishing to the catalog after creating the release
GLAB_NO_UPDATE_FLAG = '--no-update' # disables updating the release if it already exists
GLAB_NO_CLOSE_MILESTONE_FLAG = '--no-close-milestone' # disables closing the milestone after creating the release
attr_reader :job, :config
attr_reader :job, :config, :runner_manager
def initialize(job:)
@job = job
@config = job.options[:release]
@runner_manager = job.runner_manager
Gitlab::AppJsonLogger.info(
class: self.class.to_s,
@ -53,30 +44,80 @@ module Gitlab
end
def script
if catalog_publish?
[
GLAB_COMMAND_CHECK_COMMAND,
GLAB_VERSION_CHECK_COMMAND,
GLAB_LOGIN_COMMAND,
glab_create_command_with_publish_to_catalog
]
if use_glab_cli?
[script_with_glab_cli]
else
[create_command]
[script_with_release_cli]
end
end
private
def create_command
command = CREATE_BASE_COMMAND.dup
create_single_flags.each { |k, v| command.concat(" --#{k.to_s.dasherize} \"#{v}\"") }
create_array_commands.each { |k, v| v.each { |elem| command.concat(" --#{k.to_s.singularize.dasherize} \"#{elem}\"") } }
def script_with_glab_cli
if runner_manager&.platform == 'windows'
glab_windows_script
else
glab_unix_script
end
end
def glab_windows_script
<<~POWERSHELL
if (Get-Command glab -ErrorAction SilentlyContinue) {
$glabVersion = (glab --version | Select-String -Pattern '\d+\.\d+\.\d+').Matches[0].Value
if ([version]"#{GLAB_REQUIRED_VERSION}" -le [version]$glabVersion) {
#{GLAB_ENV_SET_WINDOWS}
#{GLAB_LOGIN_WINDOWS}
#{glab_create_command(GLAB_CREATE_WINDOWS)}
}
else {
Write-Output "#{GLAB_WARNING_MESSAGE}"
#{script_with_release_cli}
}
}
else {
Write-Output "#{GLAB_WARNING_MESSAGE}"
#{script_with_release_cli}
}
POWERSHELL
end
def glab_unix_script
<<~BASH
if command -v glab &> /dev/null; then
if [ "$(printf "%s\n%s" "#{GLAB_REQUIRED_VERSION}" "$(glab --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')" | sort -V | head -n1)" = "#{GLAB_REQUIRED_VERSION}" ]; then
#{GLAB_ENV_SET_UNIX}
#{GLAB_LOGIN_UNIX}
#{glab_create_command(GLAB_CREATE_UNIX)}
else
echo "#{GLAB_WARNING_MESSAGE}"
#{script_with_release_cli}
fi
else
echo "#{GLAB_WARNING_MESSAGE}"
#{script_with_release_cli}
fi
BASH
end
def script_with_release_cli
command = RELEASE_CLI_CREATE_BASE_COMMAND.dup
config.slice(*RELEASE_CLI_CREATE_SINGLE_FLAGS).each { |k, v| command.concat(" --#{k.to_s.dasherize} \"#{v}\"") }
config.slice(*RELEASE_CLI_CREATE_ARRAY_FLAGS).each { |k, v| v.each { |elem| command.concat(" --#{k.to_s.singularize.dasherize} \"#{elem}\"") } }
create_asset_links.each { |link| command.concat(" --assets-link #{stringified_json(link)}") }
if catalog_publish? && ci_release_cli_catalog_publish_option?
command.concat(" #{RELEASE_CLI_CATALOG_PUBLISH_FLAG}")
end
command.freeze
end
def glab_create_command_with_publish_to_catalog
command = GLAB_CREATE_COMMAND.dup
def glab_create_command(base_command)
command = base_command.dup
command.concat(" \"#{config[:tag_name]}\"")
command.concat(" --assets-links #{stringified_json(create_asset_links)}") if create_asset_links.present?
command.concat(" --milestone \"#{config[:milestones].join(',')}\"") if config[:milestones].present?
@ -90,18 +131,16 @@ module Gitlab
command.concat(" --ref \"#{config[:ref]}\"") if config[:ref].present?
command.concat(" --tag-message \"#{config[:tag_message]}\"") if config[:tag_message].present?
command.concat(" --released-at \"#{config[:released_at]}\"") if config[:released_at].present?
command.concat(" #{GLAB_PUBLISH_TO_CATALOG_FLAG} #{GLAB_NO_UPDATE_FLAG} #{GLAB_NO_CLOSE_MILESTONE_FLAG}")
command.concat(" #{GLAB_NO_UPDATE_FLAG} #{GLAB_NO_CLOSE_MILESTONE_FLAG}")
if catalog_publish? && ci_release_cli_catalog_publish_option?
command.concat(" #{GLAB_PUBLISH_TO_CATALOG_FLAG}")
end
command.freeze
end
def create_single_flags
config.slice(*CREATE_SINGLE_FLAGS)
end
def create_array_commands
config.slice(*CREATE_ARRAY_FLAGS)
end
def create_asset_links
config.dig(:assets, :links) || []
end
@ -111,10 +150,19 @@ module Gitlab
end
def catalog_publish?
return false if ::Feature.disabled?(:ci_release_cli_catalog_publish_option, job.project)
job.project.catalog_resource
end
strong_memoize_attr :catalog_publish?
def use_glab_cli?
::Feature.enabled?(:ci_glab_for_release, job.project)
end
strong_memoize_attr :use_glab_cli?
def ci_release_cli_catalog_publish_option?
::Feature.enabled?(:ci_release_cli_catalog_publish_option, job.project)
end
strong_memoize_attr :ci_release_cli_catalog_publish_option?
end
end
end

View File

@ -20130,6 +20130,9 @@ msgstr ""
msgid "Dependencies|There was an error fetching the projects for this group. Please try again later."
msgstr ""
msgid "Dependencies|There was an error fetching the versions for the selected component. Please try again later."
msgstr ""
msgid "Dependencies|This group exceeds the maximum number of 600 sub-groups. We cannot accurately filter or search the dependency list above this maximum. To view or filter a subset of this information, go to a subgroup's dependency list."
msgstr ""
@ -38047,10 +38050,10 @@ msgstr ""
msgid "My company or team"
msgstr ""
msgid "My topic"
msgid "My reaction"
msgstr ""
msgid "My-Reaction"
msgid "My topic"
msgstr ""
msgid "N/A"
@ -38731,6 +38734,9 @@ msgstr ""
msgid "New users set to external"
msgstr ""
msgid "New work item"
msgstr ""
msgid "New! Suggest changes directly"
msgstr ""

View File

@ -68,7 +68,7 @@
"@gitlab/ui": "111.3.1",
"@gitlab/vue-router-vue3": "npm:vue-router@4.5.0",
"@gitlab/vuex-vue3": "npm:vuex@4.1.0",
"@gitlab/web-ide": "^0.0.1-dev-20250309164831",
"@gitlab/web-ide": "^0.0.1-dev-20250320115735",
"@gleam-lang/highlight.js-gleam": "^1.5.0",
"@mattiasbuelens/web-streams-adapter": "^0.1.0",
"@rails/actioncable": "7.0.807",

View File

@ -18,9 +18,9 @@ module QA
before do
Runtime::Feature.enable(:ci_release_cli_catalog_publish_option)
Runtime::Feature.enable(:ci_glab_for_release)
Flow::Login.sign_in
Flow::Project.enable_catalog_resource_feature(project)
end

View File

@ -18,6 +18,7 @@ module QA
before do
Runtime::Feature.disable(:ci_release_cli_catalog_publish_option)
Runtime::Feature.disable(:ci_glab_for_release)
Flow::Login.sign_in
Flow::Project.enable_catalog_resource_feature(project)
@ -32,7 +33,6 @@ module QA
setup_component(project, gitlab_ci_yaml_for_create_release_with_existing_tag)
project.create_repository_tag('1.0.0')
project.visit!
Flow::Pipeline.wait_for_pipeline_creation_via_api(project: project)
project.visit_job('create-release-with-existing-tag')
@ -176,7 +176,7 @@ module QA
tags: ["#{executor}"]
create-release-with-existing-tag:
image: registry.gitlab.com/gitlab-org/release-cli:latest
image: registry.gitlab.com/gitlab-org/release-cli:v0.20.0
script:
- echo "Creating release $CI_COMMIT_TAG"
rules:
@ -197,7 +197,7 @@ module QA
- if: $CI_COMMIT_TAG != "v9.0.2" # to prevent creating a new pipeline because of the tag created in the test
create-release-with-new-tag-filled-with-information:
image: registry.gitlab.com/gitlab-org/release-cli:latest
image: registry.gitlab.com/gitlab-org/release-cli:v0.20.0
script:
- echo "Creating release $CI_COMMIT_TAG"
rules:

View File

@ -151,7 +151,7 @@ RSpec.describe 'Issue board filters', :js, feature_category: :team_planning do
describe 'filters by reaction emoji' do
before do
set_filter('my-reaction')
set_filter('reaction')
end
it 'loads all the emojis when opened and submit one as filter', :aggregate_failures do

View File

@ -23,10 +23,10 @@ RSpec.describe 'Dropdown emoji', :js, feature_category: :team_planning do
end
describe 'behavior' do
it 'does not contain My-Reaction in the list of suggestions' do
it 'does not contain My reaction in the list of suggestions' do
click_filtered_search_bar
expect(page).not_to have_link 'My-Reaction'
expect(page).not_to have_link 'My reaction'
end
end
end
@ -40,14 +40,14 @@ RSpec.describe 'Dropdown emoji', :js, feature_category: :team_planning do
describe 'behavior' do
it 'loads all the emojis when opened' do
select_tokens 'My-Reaction', '='
select_tokens 'My reaction', '='
# Expect None, Any, star, thumbsup, thumbsdown
expect_suggestion_count 5
end
it 'shows the most populated emoji at top of dropdown' do
select_tokens 'My-Reaction', '='
select_tokens 'My reaction', '='
# List items 1-3 are None, Any, divider
expect(page).to have_css('.gl-filtered-search-suggestion-list li:nth-child(4)', text: award_emoji_star.name)

View File

@ -21,7 +21,7 @@ RSpec.describe 'Dropdown hint', :js, feature_category: :team_planning do
it 'does not exist my-reaction dropdown item' do
click_filtered_search_bar
expect(page).not_to have_link 'My-reaction'
expect(page).not_to have_link 'My reaction'
end
end

View File

@ -36,7 +36,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js, feature_category: :
find_new_menu_toggle.click
aggregate_failures 'dropdown links in the navigation bar' do
expect(page).to have_link('New issue')
expect(page).to have_button('New work item')
expect(page).to have_link('New merge request')
expect(page).to have_link('New snippet', href: new_project_snippet_path(project1))
end
@ -109,7 +109,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js, feature_category: :
find_new_menu_toggle.click
aggregate_failures 'dropdown links in the navigation bar' do
expect(page).to have_link('New issue')
expect(page).to have_button('New work item')
expect(page).to have_link('New merge request')
expect(page).to have_link('New snippet', href: new_project_snippet_path(project2))
end

View File

@ -220,14 +220,14 @@ RSpec.describe 'Work items list filters', :js, feature_category: :team_planning
describe 'my-reaction' do
it 'filters', :aggregate_failures do
select_tokens 'My-Reaction', '=', AwardEmoji::THUMBS_UP, submit: true
select_tokens 'My reaction', '=', AwardEmoji::THUMBS_UP, submit: true
expect(page).to have_css('.issue', count: 1)
expect(page).to have_link(issue.title)
click_button 'Clear'
select_tokens 'My-Reaction', '!=', AwardEmoji::THUMBS_UP, submit: true
select_tokens 'My reaction', '!=', AwardEmoji::THUMBS_UP, submit: true
expect(page).to have_css('.issue', count: 2)
expect(page).to have_link(incident.title)
@ -235,7 +235,7 @@ RSpec.describe 'Work items list filters', :js, feature_category: :team_planning
click_button 'Clear'
select_tokens 'My-Reaction', '=', 'None', submit: true
select_tokens 'My reaction', '=', 'None', submit: true
expect(page).to have_css('.issue', count: 2)
expect(page).to have_link(incident.title)
@ -243,7 +243,7 @@ RSpec.describe 'Work items list filters', :js, feature_category: :team_planning
click_button 'Clear'
select_tokens 'My-Reaction', '=', 'Any', submit: true
select_tokens 'My reaction', '=', 'Any', submit: true
expect(page).to have_css('.issue', count: 1)
expect(page).to have_link(issue.title)

View File

@ -657,7 +657,7 @@ describe('CE IssuesListApp component', () => {
wrapper = mountComponent({ provide: { isSignedIn: false } });
});
it('does not render My-Reaction or Confidential tokens', () => {
it('does not render My reaction or Confidential tokens', () => {
expect(findIssuableList().props('searchTokens')).not.toMatchObject([
{ type: TOKEN_TYPE_AUTHOR, preloadedUsers: [mockCurrentUser] },
{ type: TOKEN_TYPE_ASSIGNEE, preloadedUsers: [mockCurrentUser] },

View File

@ -364,7 +364,7 @@ describe('CE ServiceDeskListApp', () => {
return waitForPromises();
});
it('does not render My-Reaction or Confidential tokens', () => {
it('does not render My reaction or Confidential tokens', () => {
expect(findIssuableList().props('searchTokens')).not.toMatchObject([
{ type: TOKEN_TYPE_AUTHOR, preloadedUsers: [mockCurrentUser] },
{ type: TOKEN_TYPE_ASSIGNEE, preloadedUsers: [mockCurrentUser] },

View File

@ -9,7 +9,7 @@ import InviteMembersTrigger from '~/invite_members/components/invite_members_tri
import CreateWorkItemModal from '~/work_items/components/create_work_item_modal.vue';
import CreateMenu from '~/super_sidebar/components/create_menu.vue';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { createNewMenuGroups } from '../mock_data';
import { createNewMenuGroups, createNewMenuProjects } from '../mock_data';
describe('CreateMenu component', () => {
let wrapper;
@ -18,22 +18,23 @@ describe('CreateMenu component', () => {
const findGlDisclosureDropdownGroups = () => wrapper.findAllComponents(GlDisclosureDropdownGroup);
const findGlDisclosureDropdownItems = () => wrapper.findAllComponents(GlDisclosureDropdownItem);
const findInviteMembersTrigger = () => wrapper.findComponent(InviteMembersTrigger);
const findCreateWorkItemModalTrigger = () =>
findGlDisclosureDropdownItems()
.filter((item) => item.props('item').text === 'New epic')
.at(0);
const findCreateWorkItemModal = () => wrapper.findComponent(CreateWorkItemModal);
const findCreateGroupWorkItemModalTrigger = () =>
wrapper.findByTestId('new-group-work-item-trigger');
const findCreateWorkItemModalTrigger = () => wrapper.findByTestId('new-work-item-trigger');
const findCreateGroupWorkItemModal = () => wrapper.findByTestId('new-group-work-item-modal');
const findCreateWorkItemModal = () => wrapper.findByTestId('new-work-item-modal');
const createWrapper = ({ provide = {} } = {}) => {
const createWrapper = ({ provide = {} } = {}, groups = createNewMenuGroups) => {
wrapper = shallowMountExtended(CreateMenu, {
provide: {
isImpersonating: false,
fullPath: 'full-path',
isGroup: false,
workItemPlanningViewEnabled: true,
...provide,
},
propsData: {
groups: createNewMenuGroups,
groups,
},
stubs: {
InviteMembersTrigger,
@ -85,7 +86,42 @@ describe('CreateMenu component', () => {
expect(findInviteMembersTrigger().exists()).toBe(true);
});
describe('create new group work item modal', () => {
it('renders work item menu item correctly', () => {
expect(findCreateGroupWorkItemModalTrigger().exists()).toBe(true);
});
it('does not render the modal by default', () => {
expect(findCreateGroupWorkItemModal().exists()).toBe(false);
});
it('shows modal when clicking work item dropdown item', async () => {
findCreateGroupWorkItemModalTrigger().vm.$emit('action');
await nextTick();
expect(findCreateGroupWorkItemModal().exists()).toBe(true);
expect(findCreateGroupWorkItemModal().props('isGroup')).toBe(true);
expect(findCreateGroupWorkItemModal().props('visible')).toBe(true);
expect(findCreateGroupWorkItemModal().props('hideButton')).toBe(true);
});
it('hides modal when hideModal event is emitted', async () => {
findCreateGroupWorkItemModalTrigger().vm.$emit('action');
await nextTick();
expect(findCreateGroupWorkItemModal().exists()).toBe(true);
findCreateGroupWorkItemModal().vm.$emit('hideModal');
await nextTick();
expect(findCreateGroupWorkItemModal().exists()).toBe(false);
});
});
describe('create new work item modal', () => {
beforeEach(() => {
createWrapper({}, createNewMenuProjects);
});
it('renders work item menu item correctly', () => {
expect(findCreateWorkItemModalTrigger().exists()).toBe(true);
});
@ -99,7 +135,7 @@ describe('CreateMenu component', () => {
await nextTick();
expect(findCreateWorkItemModal().exists()).toBe(true);
expect(findCreateWorkItemModal().props('isGroup')).toBe(true);
expect(findCreateWorkItemModal().props('isGroup')).toBe(false);
expect(findCreateWorkItemModal().props('visible')).toBe(true);
expect(findCreateWorkItemModal().props('hideButton')).toBe(true);
});

View File

@ -13,7 +13,40 @@ export const createNewMenuGroups = [
href: '/groups/new?parent_id=22#create-group-pane',
},
{
text: 'New epic',
text: 'New work item',
component: 'create_new_group_work_item_modal',
},
{
text: 'Invite members',
component: 'invite_members',
},
],
},
{
name: 'GitLab',
items: [
{
text: 'New project/repository',
href: '/projects/new',
},
{
text: 'New group',
href: '/groups/new',
},
{
text: 'New snippet',
href: '/-/snippets/new',
},
],
},
];
export const createNewMenuProjects = [
{
name: 'This project',
items: [
{
text: 'New work item',
component: 'create_new_work_item_modal',
},
{

View File

@ -153,7 +153,7 @@ describe('EmojiToken', () => {
it('renders token item when value is selected', () => {
const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
expect(tokenSegments).toHaveLength(3); // My Reaction, =, "thumbsup"
expect(tokenSegments).toHaveLength(3); // My reaction, =, "thumbsup"
expect(tokenSegments.at(2).findComponent(GlEmoji).attributes('data-name')).toEqual(
EMOJI_THUMBS_UP,
);

View File

@ -295,19 +295,44 @@ RSpec.describe Nav::NewDropdownHelper, feature_category: :navigation do
expected_menu_section(
title: 'In this project',
menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
id: 'new_issue',
title: 'New issue',
href: "/#{project.path_with_namespace}/-/issues/new",
id: 'new_work_item',
title: 'New work item',
component: 'create_new_work_item_modal',
data: {
track_action: 'click_link_new_issue',
track_action: 'click_link_new_work_item',
track_label: 'plus_menu_dropdown',
track_property: 'navigation_top',
testid: 'new_issue_link'
testid: 'new_work_item_button'
}
)
)
)
end
context 'when work_item_planning_view is disabled' do
before do
stub_feature_flags(work_item_planning_view: false)
end
it 'shows new issue menu item' do
expect(view_model[:menu_sections]).to eq(
expected_menu_section(
title: 'In this project',
menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
id: 'new_issue',
title: 'New issue',
href: "/#{project.path_with_namespace}/-/issues/new",
data: {
track_action: 'click_link_new_issue',
track_label: 'plus_menu_dropdown',
testid: 'new_issue_link',
track_property: 'navigation_top'
}
)
)
)
end
end
end
context 'with merge project' do
@ -379,14 +404,14 @@ RSpec.describe Nav::NewDropdownHelper, feature_category: :navigation do
project_section = expected_menu_section(
title: 'In this project',
menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
id: 'new_issue',
title: 'New issue',
href: "/#{project.path_with_namespace}/-/issues/new",
id: 'new_work_item',
title: 'New work item',
component: 'create_new_work_item_modal',
data: {
track_action: 'click_link_new_issue',
track_action: 'click_link_new_work_item',
track_label: 'plus_menu_dropdown',
track_property: 'navigation_top',
testid: 'new_issue_link'
testid: 'new_work_item_button'
}
)
)
@ -397,6 +422,35 @@ RSpec.describe Nav::NewDropdownHelper, feature_category: :navigation do
expect(view_model).to eq(results)
end
context 'when work_item_planning_view is disabled' do
before do
stub_feature_flags(work_item_planning_view: false)
end
it 'gives precedence to project over group' do
project_section = expected_menu_section(
title: 'In this project',
menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
id: 'new_issue',
title: 'New issue',
href: "/#{project.path_with_namespace}/-/issues/new",
data: {
track_action: 'click_link_new_issue',
track_label: 'plus_menu_dropdown',
testid: 'new_issue_link',
track_property: 'navigation_top'
}
)
)
results = {
title: title,
menu_sections: project_section
}
expect(view_model).to eq(results)
end
end
end
def expected_menu_section(title:, menu_item:)

View File

@ -70,7 +70,7 @@ RSpec.describe SidebarsHelper, feature_category: :navigation do
describe '#super_sidebar_context' do
include_context 'custom session'
let_it_be(:user) { build(:user) }
let(:user) { build(:user) }
let_it_be(:group) { build(:group) }
let_it_be(:group_with_id) { build_stubbed(:group) }
let_it_be(:panel) { {} }
@ -212,9 +212,11 @@ RSpec.describe SidebarsHelper, feature_category: :navigation do
work_items: {
full_path: group_with_id.full_path,
has_issuable_health_status_feature: "false",
has_issue_weights_feature: "false",
issues_list_path: issues_group_path(group_with_id),
labels_manage_path: group_labels_path(group_with_id),
can_admin_label: "true"
can_admin_label: "true",
work_item_planning_view_enabled: "true"
}
})
end

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::BackfillPackagesConanFileMetadataProjectId,
feature_category: :package_registry,
schema: 20250320085448 do
include_examples 'desired sharding key backfill job' do
let(:batch_table) { :packages_conan_file_metadata }
let(:backfill_column) { :project_id }
let(:backfill_via_table) { :packages_package_files }
let(:backfill_via_column) { :project_id }
let(:backfill_via_foreign_key) { :package_file_id }
end
end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::BackfillPackagesDebianFileMetadataProjectId,
feature_category: :package_registry,
schema: 20250320085929 do
include_examples 'desired sharding key backfill job' do
let(:batch_table) { :packages_debian_file_metadata }
let(:backfill_column) { :project_id }
let(:batch_column) { :package_file_id }
let(:backfill_via_table) { :packages_package_files }
let(:backfill_via_column) { :project_id }
let(:backfill_via_foreign_key) { :package_file_id }
end
end

View File

@ -31,46 +31,153 @@ RSpec.describe Gitlab::Ci::Build::Releaser, feature_category: :continuous_integr
}
end
let(:result_script) do
'release-cli create --name "Release $CI_COMMIT_SHA" --description "Created using the release-cli $EXTRA_DESCRIPTION" ' \
'--tag-name "release-$CI_COMMIT_SHA" --tag-message "Annotated tag message" --ref "$CI_COMMIT_SHA" --released-at "2020-07-15T08:00:00Z" ' \
'--milestone "m1" --milestone "m2" --milestone "m3" --assets-link "{\"name\":\"asset1\",\"url\":\"https://example.com/assets/1\",\"link_type\":\"other\",\"filepath\":\"/pretty/asset/1\"}" ' \
'--assets-link "{\"name\":\"asset2\",\"url\":\"https://example.com/assets/2\"}"'
assets_link1 = '{\"name\":\"asset1\",\"url\":\"https://example.com/assets/1\",\"link_type\":\"other\",\"filepath\":\"/pretty/asset/1\"}'
assets_link2 = '{\"name\":\"asset2\",\"url\":\"https://example.com/assets/2\"}'
glab_assets_links = "--assets-links \"[#{assets_link1},#{assets_link2}]\""
release_cli_assets_links = "--assets-link \"#{assets_link1}\" --assets-link \"#{assets_link2}\""
release_cli_command = 'release-cli create --name "Release $CI_COMMIT_SHA" --description "Created using the release-cli $EXTRA_DESCRIPTION" --tag-name "release-$CI_COMMIT_SHA" --tag-message "Annotated tag message" --ref "$CI_COMMIT_SHA" --released-at "2020-07-15T08:00:00Z" --milestone "m1" --milestone "m2" --milestone "m3"'
result_for_release_cli_without_catalog_publish = "#{release_cli_command} #{release_cli_assets_links}"
glab_create_unix = 'glab -R $CI_PROJECT_PATH release create'
glab_create_windows = 'glab -R $env:CI_PROJECT_PATH release create'
glab_command = "\"release-$CI_COMMIT_SHA\" #{glab_assets_links} --milestone \"m1,m2,m3\" --name \"Release $CI_COMMIT_SHA\" --experimental-notes-text-or-file \"Created using the release-cli $EXTRA_DESCRIPTION\" --ref \"$CI_COMMIT_SHA\" --tag-message \"Annotated tag message\" --released-at \"2020-07-15T08:00:00Z\" --no-update --no-close-milestone"
warning_message = "Warning: release-cli will not be supported after 18.0. Please use glab version >= 1.53.0. Troubleshooting: http://localhost/help/user/project/releases/_index.md#gitlab-cli-version-requirement"
unix_result_for_glab_or_release_cli_without_catalog_publish = <<~BASH
if command -v glab &> /dev/null; then
if [ "$(printf "%s\n%s" "1.53.0" "$(glab --version | grep -oE '[0-9]+.[0-9]+.[0-9]+')" | sort -V | head -n1)" = "1.53.0" ]; then
#{described_class::GLAB_ENV_SET_UNIX}
#{described_class::GLAB_LOGIN_UNIX}
#{glab_create_unix} #{glab_command}
else
echo "#{warning_message}"
#{release_cli_command} #{release_cli_assets_links}
fi
else
echo "#{warning_message}"
#{release_cli_command} #{release_cli_assets_links}
fi
BASH
windows_result_for_glab_or_release_cli_without_catalog_publish = <<~POWERSHELL
if (Get-Command glab -ErrorAction SilentlyContinue) {
$glabVersion = (glab --version | Select-String -Pattern '\d+\.\d+\.\d+').Matches[0].Value
if ([version]"1.53.0" -le [version]$glabVersion) {
#{described_class::GLAB_ENV_SET_WINDOWS}
#{described_class::GLAB_LOGIN_WINDOWS}
#{glab_create_windows} #{glab_command}
}
else {
Write-Output "#{warning_message}"
#{release_cli_command} #{release_cli_assets_links}
}
}
else {
Write-Output "#{warning_message}"
#{release_cli_command} #{release_cli_assets_links}
}
POWERSHELL
context 'on different scenarios' do
using RSpec::Parameterized::TableSyntax
where(:cli_ff, :runner_platform, :result) do
false | 'irrelevant' | result_for_release_cli_without_catalog_publish
true | 'linux' | unix_result_for_glab_or_release_cli_without_catalog_publish
true | 'windows' | windows_result_for_glab_or_release_cli_without_catalog_publish
end
with_them do
let(:runner_manager) { build(:ci_runner_machine, platform: runner_platform) }
let(:job) do
build(:ci_build,
options: { release: config[:release] },
runner: runner_manager.runner, runner_manager: runner_manager)
end
before do
stub_feature_flags(ci_glab_for_release: cli_ff)
end
it { is_expected.to eq([result]) }
end
end
it 'generates the script' do
expect(script).to eq([result_script])
end
context 'when the project is a catalog resource' do
context 'when project is a catalog resource' do
let_it_be(:project) { create(:project, :catalog_resource_with_components) }
let_it_be(:ci_catalog_resource) { create(:ci_catalog_resource, project: project) }
let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
let(:job) { build(:ci_build, pipeline: pipeline, options: { release: config[:release] }) }
result_for_release_cli_with_catalog_publish = "#{result_for_release_cli_without_catalog_publish} --catalog-publish"
unix_result_for_glab_or_release_cli_with_catalog_publish = <<~BASH
if command -v glab &> /dev/null; then
if [ "$(printf "%s\n%s" "1.53.0" "$(glab --version | grep -oE '[0-9]+.[0-9]+.[0-9]+')" | sort -V | head -n1)" = "1.53.0" ]; then
#{described_class::GLAB_ENV_SET_UNIX}
#{described_class::GLAB_LOGIN_UNIX}
#{glab_create_unix} #{glab_command} --publish-to-catalog
else
echo "#{warning_message}"
it 'generates glab scripts' do
expect(script).to eq([
"if ! command -v glab &> /dev/null; then\n " \
"echo \"Error: glab command not found. Please install glab 1.53.0 or higher. Troubleshooting: http://localhost/help/user/project/releases/_index.md#gitlab-cli-version-requirement\"\n exit 1\nfi\n",
"if [ \"$(printf \"%s\n%s\" \"1.53.0\" \"$(glab --version | grep -oE '[0-9]+.[0-9]+.[0-9]+')\" | sort -V | head -n1)\" = \"1.53.0\" ]; " \
"then\n echo \"Validating glab version. OK\"\nelse\n echo \"Error: Please use glab 1.53.0 or higher. Troubleshooting: http://localhost/help/user/project/releases/_index.md#gitlab-cli-version-requirement\"\n exit 1\nfi\n",
'glab auth login --job-token $CI_JOB_TOKEN --hostname $CI_SERVER_FQDN --api-protocol $CI_SERVER_PROTOCOL',
'GITLAB_HOST=$CI_SERVER_URL glab -R $CI_PROJECT_PATH release create "release-$CI_COMMIT_SHA" ' \
'--assets-links "[{\"name\":\"asset1\",\"url\":\"https://example.com/assets/1\",\"link_type\":\"other\",\"filepath\":\"/pretty/asset/1\"},{\"name\":\"asset2\",\"url\":\"https://example.com/assets/2\"}]" ' \
'--milestone "m1,m2,m3" --name "Release $CI_COMMIT_SHA" --experimental-notes-text-or-file "Created using the release-cli $EXTRA_DESCRIPTION" ' \
'--ref "$CI_COMMIT_SHA" --tag-message "Annotated tag message" --released-at "2020-07-15T08:00:00Z" ' \
'--publish-to-catalog --no-update --no-close-milestone'
])
end
#{release_cli_command} #{release_cli_assets_links} --catalog-publish
fi
else
echo "#{warning_message}"
context 'when the FF ci_release_cli_catalog_publish_option is disabled' do
before do
stub_feature_flags(ci_release_cli_catalog_publish_option: false)
#{release_cli_command} #{release_cli_assets_links} --catalog-publish
fi
BASH
windows_result_for_glab_or_release_cli_with_catalog_publish = <<~POWERSHELL
if (Get-Command glab -ErrorAction SilentlyContinue) {
$glabVersion = (glab --version | Select-String -Pattern '\d+\.\d+\.\d+').Matches[0].Value
if ([version]"1.53.0" -le [version]$glabVersion) {
#{described_class::GLAB_ENV_SET_WINDOWS}
#{described_class::GLAB_LOGIN_WINDOWS}
#{glab_create_windows} #{glab_command} --publish-to-catalog
}
else {
Write-Output "#{warning_message}"
#{release_cli_command} #{release_cli_assets_links} --catalog-publish
}
}
else {
Write-Output "#{warning_message}"
#{release_cli_command} #{release_cli_assets_links} --catalog-publish
}
POWERSHELL
context 'on different scenarios' do
using RSpec::Parameterized::TableSyntax
where(:cli_ff, :catalog_publish_ff, :runner_platform, :result) do
false | false | 'irrelevant' | result_for_release_cli_without_catalog_publish
false | true | 'irrelevant' | result_for_release_cli_with_catalog_publish
true | false | 'linux' | unix_result_for_glab_or_release_cli_without_catalog_publish
true | true | 'linux' | unix_result_for_glab_or_release_cli_with_catalog_publish
true | false | 'windows' | windows_result_for_glab_or_release_cli_without_catalog_publish
true | true | 'windows' | windows_result_for_glab_or_release_cli_with_catalog_publish
end
it 'generates the release-cli script' do
expect(script).to eq([result_script])
with_them do
let(:runner_manager) { build(:ci_runner_machine, platform: runner_platform) }
let(:job) do
build(:ci_build, pipeline: pipeline,
options: { release: config[:release] },
runner: runner_manager.runner, runner_manager: runner_manager)
end
before do
stub_feature_flags(ci_glab_for_release: cli_ff)
stub_feature_flags(ci_release_cli_catalog_publish_option: catalog_publish_ff)
end
it { is_expected.to eq([result]) }
end
end
end
@ -99,14 +206,14 @@ RSpec.describe Gitlab::Ci::Build::Releaser, feature_category: :continuous_integr
links = { links: [{ name: 'asset1', url: 'https://example.com/assets/1', link_type: 'other', filepath: '/pretty/asset/1' }] }
where(:node_name, :node_value, :result) do
:name | 'Release $CI_COMMIT_SHA' | 'release-cli create --name "Release $CI_COMMIT_SHA"'
:description | 'Release-cli $EXTRA_DESCRIPTION' | 'release-cli create --description "Release-cli $EXTRA_DESCRIPTION"'
:tag_name | 'release-$CI_COMMIT_SHA' | 'release-cli create --tag-name "release-$CI_COMMIT_SHA"'
:tag_message | 'Annotated tag message' | 'release-cli create --tag-message "Annotated tag message"'
:ref | '$CI_COMMIT_SHA' | 'release-cli create --ref "$CI_COMMIT_SHA"'
:milestones | %w[m1 m2 m3] | 'release-cli create --milestone "m1" --milestone "m2" --milestone "m3"'
:released_at | '2020-07-15T08:00:00Z' | 'release-cli create --released-at "2020-07-15T08:00:00Z"'
:assets | links | "release-cli create --assets-link #{links[:links][0].to_json.to_json}"
:name | 'Release $CI_COMMIT_SHA' | 'glab -R $CI_PROJECT_PATH release create "" --name "Release $CI_COMMIT_SHA"'
:description | 'Release-cli $EXTRA_DESCRIPTION' | 'glab -R $CI_PROJECT_PATH release create "" --experimental-notes-text-or-file "Release-cli $EXTRA_DESCRIPTION"'
:tag_name | 'release-$CI_COMMIT_SHA' | 'glab -R $CI_PROJECT_PATH release create "release-$CI_COMMIT_SHA"'
:tag_message | 'Annotated tag message' | 'glab -R $CI_PROJECT_PATH release create "" --tag-message "Annotated tag message"'
:ref | '$CI_COMMIT_SHA' | 'glab -R $CI_PROJECT_PATH release create "" --ref "$CI_COMMIT_SHA"'
:milestones | %w[m1 m2 m3] | 'glab -R $CI_PROJECT_PATH release create "" --milestone "m1,m2,m3"'
:released_at | '2020-07-15T08:00:00Z' | 'glab -R $CI_PROJECT_PATH release create "" --released-at "2020-07-15T08:00:00Z"'
:assets | links | "glab -R $CI_PROJECT_PATH release create \"\" --assets-links #{links[:links].to_json.to_json}"
end
with_them do
@ -119,7 +226,38 @@ RSpec.describe Gitlab::Ci::Build::Releaser, feature_category: :continuous_integr
end
it 'generates the script' do
expect(script).to eq([result])
expect(script).to match([a_string_including(result)])
end
end
context 'when the FF ci_glab_for_release is disabled' do
before do
stub_feature_flags(ci_glab_for_release: false)
end
where(:node_name, :node_value, :result) do
:name | 'Release $CI_COMMIT_SHA' | 'release-cli create --name "Release $CI_COMMIT_SHA"'
:description | 'Release-cli $EXTRA_DESCRIPTION' | 'release-cli create --description "Release-cli $EXTRA_DESCRIPTION"'
:tag_name | 'release-$CI_COMMIT_SHA' | 'release-cli create --tag-name "release-$CI_COMMIT_SHA"'
:tag_message | 'Annotated tag message' | 'release-cli create --tag-message "Annotated tag message"'
:ref | '$CI_COMMIT_SHA' | 'release-cli create --ref "$CI_COMMIT_SHA"'
:milestones | %w[m1 m2 m3] | 'release-cli create --milestone "m1" --milestone "m2" --milestone "m3"'
:released_at | '2020-07-15T08:00:00Z' | 'release-cli create --released-at "2020-07-15T08:00:00Z"'
:assets | links | "release-cli create --assets-link #{links[:links][0].to_json.to_json}"
end
with_them do
let(:config) do
{
release: {
node_name => node_value
}
}
end
it 'generates the script' do
expect(script).to eq([result])
end
end
end
end

View File

@ -61,8 +61,18 @@ RSpec.describe Gitlab::Ci::Build::Step, feature_category: :continuous_integratio
context 'with release' do
let(:job) { create(:ci_build, :release_options) }
it 'returns the release-cli command line' do
expect(subject.script).to eq(["release-cli create --name \"Release $CI_COMMIT_SHA\" --description \"Created using the release-cli $EXTRA_DESCRIPTION\" --tag-name \"release-$CI_COMMIT_SHA\" --ref \"$CI_COMMIT_SHA\" --assets-link \"{\\\"name\\\":\\\"asset1\\\",\\\"url\\\":\\\"https://example.com/assets/1\\\"}\""])
it 'returns glab command line' do
expect(subject.script).to match_array([a_string_including("glab -R $CI_PROJECT_PATH release create")])
end
context 'when the FF ci_glab_for_release is disabled' do
before do
stub_feature_flags(ci_glab_for_release: false)
end
it 'returns release-cli command line' do
expect(subject.script).to match_array([a_string_including("release-cli create --name")])
end
end
end
@ -81,31 +91,30 @@ RSpec.describe Gitlab::Ci::Build::Step, feature_category: :continuous_integratio
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:job) { create(:ci_build, :release_options, pipeline: pipeline) }
it 'returns glab scripts' do
expect(subject.script).to eq([
"if ! command -v glab &> /dev/null; then\n " \
"echo \"Error: glab command not found. Please install glab 1.53.0 or higher. Troubleshooting: http://localhost/help/user/project/releases/_index.md#gitlab-cli-version-requirement\"\n exit 1\nfi\n",
"if [ \"$(printf \"%s\n%s\" \"1.53.0\" \"$(glab --version | grep -oE '[0-9]+.[0-9]+.[0-9]+')\" | sort -V | head -n1)\" = \"1.53.0\" ]; " \
"then\n echo \"Validating glab version. OK\"\nelse\n echo \"Error: Please use glab 1.53.0 or higher. Troubleshooting: http://localhost/help/user/project/releases/_index.md#gitlab-cli-version-requirement\"\n exit 1\nfi\n",
'glab auth login --job-token $CI_JOB_TOKEN --hostname $CI_SERVER_FQDN --api-protocol $CI_SERVER_PROTOCOL',
'GITLAB_HOST=$CI_SERVER_URL glab -R $CI_PROJECT_PATH release create "release-$CI_COMMIT_SHA" ' \
'--assets-links "[{\"name\":\"asset1\",\"url\":\"https://example.com/assets/1\"}]" ' \
'--name "Release $CI_COMMIT_SHA" --experimental-notes-text-or-file "Created using the release-cli $EXTRA_DESCRIPTION" ' \
'--ref "$CI_COMMIT_SHA" --publish-to-catalog --no-update --no-close-milestone'
])
it 'returns glab scripts with catalog publish' do
expect(subject.script).to match_array([a_string_including("glab -R $CI_PROJECT_PATH release create")])
expect(subject.script).to match_array([a_string_including("--publish-to-catalog")])
end
context 'when the FF ci_glab_for_release is disabled' do
before do
stub_feature_flags(ci_glab_for_release: false)
end
it 'returns release-cli script with catalog publish' do
expect(subject.script).to match_array([a_string_including("release-cli create")])
expect(subject.script).to match_array([a_string_including("--catalog-publish")])
end
end
context 'when the FF ci_release_cli_catalog_publish_option is disabled' do
before do
stub_feature_flags(ci_release_cli_catalog_publish_option: false)
stub_feature_flags(ci_release_cli_catalog_publish_option: false, ci_glab_for_release: false)
end
it 'returns the release-cli script' do
expect(subject.script).to eq([
"release-cli create --name \"Release $CI_COMMIT_SHA\" --description \"Created using the release-cli $EXTRA_DESCRIPTION\" " \
"--tag-name \"release-$CI_COMMIT_SHA\" --ref \"$CI_COMMIT_SHA\" " \
'--assets-link "{\"name\":\"asset1\",\"url\":\"https://example.com/assets/1\"}"'
])
it 'returns the release-cli script with catalog publish' do
expect(subject.script).to match_array([a_string_including("release-cli create")])
expect(subject.script).not_to match_array([a_string_including("--catalog-publish")])
end
end
end

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::LooseForeignKeys do
RSpec.describe Gitlab::Database::LooseForeignKeys, feature_category: :cell do
describe 'verify all definitions' do
subject(:definitions) { described_class.definitions }
@ -41,6 +41,62 @@ RSpec.describe Gitlab::Database::LooseForeignKeys do
end
end
context 'ensure no partitions are included' do
let(:all_source_tables) do
YAML
.load_file(described_class.loose_foreign_keys_yaml_path)
.values.flat_map { |sources| sources.pluck(:table) }
.uniq
end
let(:included_partitioned_tables) do
Gitlab::Database::PostgresPartition.where(name: all_source_tables)
end
it 'does not include partitions as source tables' do
expect(included_partitioned_tables).to be_blank, <<~END
Please remove these partitions #{included_partitioned_tables.map(&:name).join(', ')}.
And include their partitioned tables #{included_partitioned_tables.map(&:parent_identifier)} instead
if you haven't done so.
END
end
end
context 'for all partitioned tables' do
let(:tables_with_trigger) do
Gitlab::Database::PostgresPartitionedTable
.connection.select_values(<<~SQL)
SELECT event_object_table
FROM information_schema.triggers
WHERE action_statement LIKE '%insert_into_loose_foreign_keys_deleted_records_override_table%'
SQL
end
let(:partitioned_tables_without_trigger) do
partitioned_tables
.pluck(:name)
.reject { |table| tables_with_trigger.include?(table) }
end
let(:partitioned_tables) do
Gitlab::Database::PostgresPartitionedTable.where(name: all_source_tables)
end
let(:all_source_tables) do
YAML
.load_file(described_class.loose_foreign_keys_yaml_path)
.values.flat_map { |sources| sources.pluck(:table) }
.uniq
end
it 'has installed trigger for all partitioned tables' do
expect(partitioned_tables_without_trigger).to be_blank, <<~END
#{partitioned_tables_without_trigger.join(',')} need(s) LFK trigger.
Please create migration using `track_record_deletions_override_table_name` to install the trigger.
END
end
end
context 'ensure no duplicates are found' do
it 'does not have duplicate tables defined' do
# since we use hash to detect duplicate hash keys we need to parse YAML document

View File

@ -0,0 +1,33 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe QueueBackfillPackagesConanFileMetadataProjectId, feature_category: :package_registry do
let!(:batched_migration) { described_class::MIGRATION }
it 'schedules a new batched migration' do
reversible_migration do |migration|
migration.before -> {
expect(batched_migration).not_to have_scheduled_batched_migration
}
migration.after -> {
expect(batched_migration).to have_scheduled_batched_migration(
table_name: :packages_conan_file_metadata,
column_name: :id,
interval: described_class::DELAY_INTERVAL,
batch_size: described_class::BATCH_SIZE,
sub_batch_size: described_class::SUB_BATCH_SIZE,
gitlab_schema: :gitlab_main_cell,
job_arguments: [
:project_id,
:packages_package_files,
:project_id,
:package_file_id
]
)
}
end
end
end

View File

@ -0,0 +1,33 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe QueueBackfillPackagesDebianFileMetadataProjectId, feature_category: :package_registry do
let!(:batched_migration) { described_class::MIGRATION }
it 'schedules a new batched migration' do
reversible_migration do |migration|
migration.before -> {
expect(batched_migration).not_to have_scheduled_batched_migration
}
migration.after -> {
expect(batched_migration).to have_scheduled_batched_migration(
table_name: :packages_debian_file_metadata,
column_name: :package_file_id,
interval: described_class::DELAY_INTERVAL,
batch_size: described_class::BATCH_SIZE,
sub_batch_size: described_class::SUB_BATCH_SIZE,
gitlab_schema: :gitlab_main_cell,
job_arguments: [
:project_id,
:packages_package_files,
:project_id,
:package_file_id
]
)
}
end
end
end

View File

@ -429,7 +429,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state, feature_catego
expect(response).to have_gitlab_http_status(:created)
expect(response.headers).not_to have_key('X-GitLab-Last-Update')
expect(json_response['steps']).to eq(
expect(json_response['steps']).to match_array(
[
{
"name" => "script",
@ -440,14 +440,43 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state, feature_catego
},
{
"name" => "release",
"script" =>
["release-cli create --name \"Release $CI_COMMIT_SHA\" --description \"Created using the release-cli $EXTRA_DESCRIPTION\" --tag-name \"release-$CI_COMMIT_SHA\" --ref \"$CI_COMMIT_SHA\" --assets-link \"{\\\"name\\\":\\\"asset1\\\",\\\"url\\\":\\\"https://example.com/assets/1\\\"}\""],
"script" => [a_string_including("glab -R $CI_PROJECT_PATH release create")],
"timeout" => 3600,
"when" => "on_success",
"allow_failure" => false
}
])
end
context 'when the FF ci_glab_for_release is disabled' do
before do
stub_feature_flags(ci_glab_for_release: false)
end
it 'exposes release info' do
request_job info: { features: { multi_build_steps: true } }
expect(response).to have_gitlab_http_status(:created)
expect(response.headers).not_to have_key('X-GitLab-Last-Update')
expect(json_response['steps']).to match_array(
[
{
"name" => "script",
"script" => ["make changelog | tee release_changelog.txt"],
"timeout" => 3600,
"when" => "on_success",
"allow_failure" => false
},
{
"name" => "release",
"script" => [a_string_including("release-cli create --name ")],
"timeout" => 3600,
"when" => "on_success",
"allow_failure" => false
}
])
end
end
end
context 'when `multi_build_steps` is not passed by the runner' do

View File

@ -226,12 +226,7 @@ RSpec.describe Organizations::OrganizationsController, feature_category: :cell d
resource_parent_path = json_response['events'].first["resource_parent"]["full_path"]
expect(json_response['events'].size).to eq(1)
expect(resource_parent_path).to eq(recently_updated_project.full_path), <<~ERROR.squish
Expected project with path #{recently_updated_project.full_path}
(last_activity_at: #{recently_updated_project.last_activity_at}),
but got #{resource_parent_path || 'nil'}.
Stale project: #{stale_project.full_path} last_activity_at: #{stale_project.last_activity_at}).
ERROR
expect(resource_parent_path).to eq(recently_updated_project.full_path)
end
end

View File

@ -148,9 +148,9 @@ module FilteredSearchHelpers
def reaction_token(reaction_name = nil, is_emoji = true)
if is_emoji
{ name: 'My-Reaction', emoji_name: reaction_name }
{ name: 'My reaction', emoji_name: reaction_name }
else
create_token('My-Reaction', reaction_name)
create_token('My reaction', reaction_name)
end
end

View File

@ -134,6 +134,7 @@ export default {
totalSize: 0,
ready: false,
hoverKey: null,
rootSizings: {},
}
},
@ -202,17 +203,22 @@ export default {
},
mounted () {
this.applyPageMode()
this.applyPageMode();
this.$nextTick(() => {
// In SSR mode, render the real number of visible items
this.$_prerender = false
this.updateVisibleItems(true)
this.updateVisibleItems(true);
this.ready = true
})
this.$nextTick(() => {
this.cacheSizings();
});
});
this.$el.addEventListener('scroll', this.cacheSizings, false);
},
beforeDestroy () {
this.removeListeners()
this.removeListeners();
this.$el.removeEventListener('scroll', this.cacheSizings, false);
},
methods: {
@ -225,7 +231,7 @@ export default {
// FIXME: replace with markRaw in Vue3
// See https://gitlab.com/gitlab-org/gitlab/-/issues/395772
__v_skip: true,
id: uid++,
index,
used: true,
@ -257,10 +263,22 @@ export default {
},
handleResize () {
this.cacheSizings();
this.$emit('resize')
if (this.ready) this.updateVisibleItems(false)
},
cacheSizings() {
if (this.pageMode) return;
const target = this.$el;
this.rootSizings = {
scrollTop: target.scrollTop,
scrollLeft: target.scrollLeft,
clientWidth: target.clientWidth,
clientHeight: target.clientHeight,
};
},
handleScroll (event) {
if (!this.$_scrollDirty) {
this.$_scrollDirty = true
@ -536,13 +554,13 @@ export default {
}
} else if (isVertical) {
scrollState = {
start: el.scrollTop,
end: el.scrollTop + el.clientHeight,
start: this.rootSizings.scrollTop ?? el.scrollTop,
end: (this.rootSizings.scrollTop ?? el.scrollTop) + (this.rootSizings.clientHeight ?? el.clientHeight),
}
} else {
scrollState = {
start: el.scrollLeft,
end: el.scrollLeft + el.clientWidth,
start: this.rootSizings.scrollLeft ?? el.scrollLeft,
end: (this.rootSizings.scrollLeft ?? el.scrollLeft) + (this.rootSizings.clientWidth ?? el.clientWidth),
}
}

View File

@ -1469,10 +1469,10 @@
dependencies:
"@vue/devtools-api" "^6.0.0-beta.11"
"@gitlab/web-ide@^0.0.1-dev-20250309164831":
version "0.0.1-dev-20250309164831"
resolved "https://registry.yarnpkg.com/@gitlab/web-ide/-/web-ide-0.0.1-dev-20250309164831.tgz#8026968bebaee20ff7c387afccbfaa5505176598"
integrity sha512-Jfk4DXElRJGs03iRO2t/cw2Ljg4Y5XvKydfuv0REmhtsgP7vmomPnc62BXDcpsFnIkInA4vTgfqhgFqIQLBKEw==
"@gitlab/web-ide@^0.0.1-dev-20250320115735":
version "0.0.1-dev-20250320115735"
resolved "https://registry.yarnpkg.com/@gitlab/web-ide/-/web-ide-0.0.1-dev-20250320115735.tgz#4357486b82fecfdc48fe620bb688a158f745ded2"
integrity sha512-aPgFLey49HmMkhhQfpFj1kGC81q9N+9uQhOsbnD/b6hnuMaUu5PZNrfor/d3kqFEl53ju4AQb5uerxUF8hwZ1Q==
"@gleam-lang/highlight.js-gleam@^1.5.0":
version "1.5.0"