Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
a1384a9c4f
commit
c7d68cbee7
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -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 = '#';
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1 @@
|
|||
6720c41831aee47380b8a7bfa83f1d3e61d73fb4f93f87d74e231534b50a897d
|
||||
|
|
@ -0,0 +1 @@
|
|||
be35fa15e3dd3baba7bce0c45b295030a7743836a18fe2bf1770ecd281e6466b
|
||||
|
|
@ -0,0 +1 @@
|
|||
248df833e5ca809fb315368a6aea8d86f4a853b226fa371e95b399653209f174
|
||||
|
|
@ -0,0 +1 @@
|
|||
a1b96646a07be6c331dd8a58b921c2ca1ca123fb324db000c97752fbe5e94a6a
|
||||
|
|
@ -0,0 +1 @@
|
|||
3bf6398499bcd35cd892af37b66aadf75c86515313db07718f9191feba4aee6e
|
||||
|
|
@ -0,0 +1 @@
|
|||
c110adc24435dcae929fb05418f00e4ef6bfce14545078a2a43445777ad298ba
|
||||
|
|
@ -0,0 +1 @@
|
|||
e6175b08a9c6528ae9a88c0187aabf3190a9f9270b9682b2253f5051914580c0
|
||||
|
|
@ -0,0 +1 @@
|
|||
4fb2f62a71ffaf9ff219dcab1071b28f6ba4f405039365e39494abeb806dfdaf
|
||||
|
|
@ -0,0 +1 @@
|
|||
955191ee0d02bb2ba449cf57317f4a0f950f058bf96affc7ade0ce9c120f854b
|
||||
|
|
@ -0,0 +1 @@
|
|||
b069bbd4e314a2eab14e1c56361686e38576bb1514cee2e5659fff9e13cee4ed
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 >}}
|
||||
|
|
|
|||
|
|
@ -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. |
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ""
|
||||
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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] },
|
||||
|
|
|
|||
|
|
@ -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] },
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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:)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Reference in New Issue