Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
240609275d
commit
e838c62efb
|
@ -1,16 +0,0 @@
|
||||||
import Vue from 'vue';
|
|
||||||
import DeleteLabelModal from '~/vue_shared/components/delete_label_modal.vue';
|
|
||||||
|
|
||||||
const mountDeleteLabelModal = (optionalProps) =>
|
|
||||||
new Vue({
|
|
||||||
render(h) {
|
|
||||||
return h(DeleteLabelModal, {
|
|
||||||
props: {
|
|
||||||
selector: '.js-delete-label-modal-button',
|
|
||||||
...optionalProps,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}).$mount();
|
|
||||||
|
|
||||||
export default (optionalProps = {}) => mountDeleteLabelModal(optionalProps);
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
import $ from 'jquery';
|
||||||
|
import Vue from 'vue';
|
||||||
|
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
|
||||||
|
import Translate from '~/vue_shared/translate';
|
||||||
|
import DeleteLabelModal from './components/delete_label_modal.vue';
|
||||||
|
import PromoteLabelModal from './components/promote_label_modal.vue';
|
||||||
|
import eventHub from './event_hub';
|
||||||
|
import GroupLabelSubscription from './group_label_subscription';
|
||||||
|
import LabelManager from './label_manager';
|
||||||
|
import ProjectLabelSubscription from './project_label_subscription';
|
||||||
|
|
||||||
|
export function initDeleteLabelModal(optionalProps = {}) {
|
||||||
|
new Vue({
|
||||||
|
render(h) {
|
||||||
|
return h(DeleteLabelModal, {
|
||||||
|
props: {
|
||||||
|
selector: '.js-delete-label-modal-button',
|
||||||
|
...optionalProps,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}).$mount();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initLabels() {
|
||||||
|
if ($('.prioritized-labels').length) {
|
||||||
|
new LabelManager(); // eslint-disable-line no-new
|
||||||
|
}
|
||||||
|
$('.label-subscription').each((i, el) => {
|
||||||
|
const $el = $(el);
|
||||||
|
|
||||||
|
if ($el.find('.dropdown-group-label').length) {
|
||||||
|
new GroupLabelSubscription($el); // eslint-disable-line no-new
|
||||||
|
} else {
|
||||||
|
new ProjectLabelSubscription($el); // eslint-disable-line no-new
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initLabelIndex() {
|
||||||
|
Vue.use(Translate);
|
||||||
|
|
||||||
|
initLabels();
|
||||||
|
initDeleteLabelModal();
|
||||||
|
|
||||||
|
const onRequestFinished = ({ labelUrl, successful }) => {
|
||||||
|
const button = document.querySelector(
|
||||||
|
`.js-promote-project-label-button[data-url="${labelUrl}"]`,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!successful) {
|
||||||
|
button.removeAttribute('disabled');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onRequestStarted = (labelUrl) => {
|
||||||
|
const button = document.querySelector(
|
||||||
|
`.js-promote-project-label-button[data-url="${labelUrl}"]`,
|
||||||
|
);
|
||||||
|
button.setAttribute('disabled', '');
|
||||||
|
eventHub.$once('promoteLabelModal.requestFinished', onRequestFinished);
|
||||||
|
};
|
||||||
|
|
||||||
|
const promoteLabelButtons = document.querySelectorAll('.js-promote-project-label-button');
|
||||||
|
|
||||||
|
return new Vue({
|
||||||
|
el: '#js-promote-label-modal',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
modalProps: {
|
||||||
|
labelTitle: '',
|
||||||
|
labelColor: '',
|
||||||
|
labelTextColor: '',
|
||||||
|
url: '',
|
||||||
|
groupName: '',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
eventHub.$on('promoteLabelModal.props', this.setModalProps);
|
||||||
|
eventHub.$emit('promoteLabelModal.mounted');
|
||||||
|
|
||||||
|
promoteLabelButtons.forEach((button) => {
|
||||||
|
button.removeAttribute('disabled');
|
||||||
|
button.addEventListener('click', () => {
|
||||||
|
this.$root.$emit(BV_SHOW_MODAL, 'promote-label-modal');
|
||||||
|
eventHub.$once('promoteLabelModal.requestStarted', onRequestStarted);
|
||||||
|
|
||||||
|
this.setModalProps({
|
||||||
|
labelTitle: button.dataset.labelTitle,
|
||||||
|
labelColor: button.dataset.labelColor,
|
||||||
|
labelTextColor: button.dataset.labelTextColor,
|
||||||
|
url: button.dataset.url,
|
||||||
|
groupName: button.dataset.groupName,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
eventHub.$off('promoteLabelModal.props', this.setModalProps);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setModalProps(modalProps) {
|
||||||
|
this.modalProps = modalProps;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
render(createElement) {
|
||||||
|
return createElement(PromoteLabelModal, {
|
||||||
|
props: this.modalProps,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initAdminLabels() {
|
||||||
|
const pagination = document.querySelector('.labels .gl-pagination');
|
||||||
|
const emptyState = document.querySelector('.labels .nothing-here-block.hidden');
|
||||||
|
|
||||||
|
function removeLabelSuccessCallback() {
|
||||||
|
this.closest('li').classList.add('gl-display-none!');
|
||||||
|
|
||||||
|
const labelsCount = document.querySelectorAll(
|
||||||
|
'ul.manage-labels-list li:not(.gl-display-none\\!)',
|
||||||
|
).length;
|
||||||
|
|
||||||
|
// display the empty state if there are no more labels
|
||||||
|
if (labelsCount < 1 && !pagination && emptyState) {
|
||||||
|
emptyState.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.querySelectorAll('.js-remove-label').forEach((row) => {
|
||||||
|
row.addEventListener('ajax:success', removeLabelSuccessCallback);
|
||||||
|
});
|
||||||
|
}
|
|
@ -1,19 +0,0 @@
|
||||||
import $ from 'jquery';
|
|
||||||
import GroupLabelSubscription from './group_label_subscription';
|
|
||||||
import LabelManager from './label_manager';
|
|
||||||
import ProjectLabelSubscription from './project_label_subscription';
|
|
||||||
|
|
||||||
export default () => {
|
|
||||||
if ($('.prioritized-labels').length) {
|
|
||||||
new LabelManager(); // eslint-disable-line no-new
|
|
||||||
}
|
|
||||||
$('.label-subscription').each((i, el) => {
|
|
||||||
const $el = $(el);
|
|
||||||
|
|
||||||
if ($el.find('.dropdown-group-label').length) {
|
|
||||||
new GroupLabelSubscription($el); // eslint-disable-line no-new
|
|
||||||
} else {
|
|
||||||
new ProjectLabelSubscription($el); // eslint-disable-line no-new
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -9,7 +9,7 @@ import { isScopedLabel } from '~/lib/utils/common_utils';
|
||||||
import createFlash from '~/flash';
|
import createFlash from '~/flash';
|
||||||
import axios from '~/lib/utils/axios_utils';
|
import axios from '~/lib/utils/axios_utils';
|
||||||
import { sprintf, __ } from '~/locale';
|
import { sprintf, __ } from '~/locale';
|
||||||
import CreateLabelDropdown from './create_label';
|
import CreateLabelDropdown from './create_label_dropdown';
|
||||||
|
|
||||||
export default class LabelsSelect {
|
export default class LabelsSelect {
|
||||||
constructor(els, options = {}) {
|
constructor(els, options = {}) {
|
||||||
|
|
|
@ -1,23 +1,3 @@
|
||||||
function initLabels() {
|
import { initAdminLabels } from '~/labels';
|
||||||
const pagination = document.querySelector('.labels .gl-pagination');
|
|
||||||
const emptyState = document.querySelector('.labels .nothing-here-block.hidden');
|
|
||||||
|
|
||||||
function removeLabelSuccessCallback() {
|
initAdminLabels();
|
||||||
this.closest('li').classList.add('gl-display-none!');
|
|
||||||
|
|
||||||
const labelsCount = document.querySelectorAll(
|
|
||||||
'ul.manage-labels-list li:not(.gl-display-none\\!)',
|
|
||||||
).length;
|
|
||||||
|
|
||||||
// display the empty state if there are no more labels
|
|
||||||
if (labelsCount < 1 && !pagination && emptyState) {
|
|
||||||
emptyState.classList.remove('hidden');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.querySelectorAll('.js-remove-label').forEach((row) => {
|
|
||||||
row.addEventListener('ajax:success', removeLabelSuccessCallback);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
initLabels();
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import initDeleteLabelModal from '~/labels/delete_label_modal';
|
import { initDeleteLabelModal, initLabels } from '~/labels';
|
||||||
import initLabels from '~/labels/init_labels';
|
|
||||||
|
|
||||||
initLabels();
|
initLabels();
|
||||||
initDeleteLabelModal();
|
initDeleteLabelModal();
|
||||||
|
|
|
@ -1,83 +1,3 @@
|
||||||
import Vue from 'vue';
|
import { initLabelIndex } from '~/labels';
|
||||||
import initDeleteLabelModal from '~/labels/delete_label_modal';
|
|
||||||
import initLabels from '~/labels/init_labels';
|
|
||||||
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
|
|
||||||
import Translate from '~/vue_shared/translate';
|
|
||||||
import PromoteLabelModal from '../components/promote_label_modal.vue';
|
|
||||||
import eventHub from '../event_hub';
|
|
||||||
|
|
||||||
Vue.use(Translate);
|
|
||||||
|
|
||||||
const initLabelIndex = () => {
|
|
||||||
initLabels();
|
|
||||||
initDeleteLabelModal();
|
|
||||||
|
|
||||||
const onRequestFinished = ({ labelUrl, successful }) => {
|
|
||||||
const button = document.querySelector(
|
|
||||||
`.js-promote-project-label-button[data-url="${labelUrl}"]`,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!successful) {
|
|
||||||
button.removeAttribute('disabled');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onRequestStarted = (labelUrl) => {
|
|
||||||
const button = document.querySelector(
|
|
||||||
`.js-promote-project-label-button[data-url="${labelUrl}"]`,
|
|
||||||
);
|
|
||||||
button.setAttribute('disabled', '');
|
|
||||||
eventHub.$once('promoteLabelModal.requestFinished', onRequestFinished);
|
|
||||||
};
|
|
||||||
|
|
||||||
const promoteLabelButtons = document.querySelectorAll('.js-promote-project-label-button');
|
|
||||||
|
|
||||||
return new Vue({
|
|
||||||
el: '#js-promote-label-modal',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
modalProps: {
|
|
||||||
labelTitle: '',
|
|
||||||
labelColor: '',
|
|
||||||
labelTextColor: '',
|
|
||||||
url: '',
|
|
||||||
groupName: '',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
eventHub.$on('promoteLabelModal.props', this.setModalProps);
|
|
||||||
eventHub.$emit('promoteLabelModal.mounted');
|
|
||||||
|
|
||||||
promoteLabelButtons.forEach((button) => {
|
|
||||||
button.removeAttribute('disabled');
|
|
||||||
button.addEventListener('click', () => {
|
|
||||||
this.$root.$emit(BV_SHOW_MODAL, 'promote-label-modal');
|
|
||||||
eventHub.$once('promoteLabelModal.requestStarted', onRequestStarted);
|
|
||||||
|
|
||||||
this.setModalProps({
|
|
||||||
labelTitle: button.dataset.labelTitle,
|
|
||||||
labelColor: button.dataset.labelColor,
|
|
||||||
labelTextColor: button.dataset.labelTextColor,
|
|
||||||
url: button.dataset.url,
|
|
||||||
groupName: button.dataset.groupName,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
eventHub.$off('promoteLabelModal.props', this.setModalProps);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
setModalProps(modalProps) {
|
|
||||||
this.modalProps = modalProps;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
render(createElement) {
|
|
||||||
return createElement(PromoteLabelModal, {
|
|
||||||
props: this.modalProps,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
initLabelIndex();
|
initLabelIndex();
|
||||||
|
|
|
@ -195,12 +195,12 @@ export default {
|
||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
<dropdown-header
|
<dropdown-header
|
||||||
v-if="!isStandalone"
|
|
||||||
ref="header"
|
ref="header"
|
||||||
v-model="searchKey"
|
:search-key="searchKey"
|
||||||
:labels-create-title="labelsCreateTitle"
|
:labels-create-title="labelsCreateTitle"
|
||||||
:labels-list-title="labelsListTitle"
|
:labels-list-title="labelsListTitle"
|
||||||
:show-dropdown-contents-create-view="showDropdownContentsCreateView"
|
:show-dropdown-contents-create-view="showDropdownContentsCreateView"
|
||||||
|
:is-standalone="isStandalone"
|
||||||
@toggleDropdownContentsCreateView="toggleDropdownContent"
|
@toggleDropdownContentsCreateView="toggleDropdownContent"
|
||||||
@closeDropdown="$emit('closeDropdown')"
|
@closeDropdown="$emit('closeDropdown')"
|
||||||
@input="debouncedSearchKeyUpdate"
|
@input="debouncedSearchKeyUpdate"
|
||||||
|
|
|
@ -6,9 +6,6 @@ export default {
|
||||||
GlButton,
|
GlButton,
|
||||||
GlSearchBoxByType,
|
GlSearchBoxByType,
|
||||||
},
|
},
|
||||||
model: {
|
|
||||||
prop: 'searchKey',
|
|
||||||
},
|
|
||||||
props: {
|
props: {
|
||||||
labelsCreateTitle: {
|
labelsCreateTitle: {
|
||||||
type: String,
|
type: String,
|
||||||
|
@ -31,6 +28,11 @@ export default {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
isStandalone: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
dropdownTitle() {
|
dropdownTitle() {
|
||||||
|
@ -47,7 +49,11 @@ export default {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div data-testid="dropdown-header">
|
<div data-testid="dropdown-header">
|
||||||
<div class="dropdown-title gl-display-flex gl-align-items-center gl-pt-0 gl-pb-3!">
|
<div
|
||||||
|
v-if="!isStandalone"
|
||||||
|
class="dropdown-title gl-display-flex gl-align-items-center gl-pt-0 gl-pb-3!"
|
||||||
|
data-testid="dropdown-header-title"
|
||||||
|
>
|
||||||
<gl-button
|
<gl-button
|
||||||
v-if="showDropdownContentsCreateView"
|
v-if="showDropdownContentsCreateView"
|
||||||
:aria-label="__('Go back')"
|
:aria-label="__('Go back')"
|
||||||
|
|
|
@ -286,7 +286,7 @@ export default {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="labels-select-wrapper position-relative"
|
class="labels-select-wrapper gl-relative"
|
||||||
:class="{
|
:class="{
|
||||||
'is-standalone': isDropdownVariantStandalone(variant),
|
'is-standalone': isDropdownVariantStandalone(variant),
|
||||||
'is-embedded': isDropdownVariantEmbedded(variant),
|
'is-embedded': isDropdownVariantEmbedded(variant),
|
||||||
|
|
|
@ -83,8 +83,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
|
||||||
:ci_environments_status,
|
:ci_environments_status,
|
||||||
:destroy,
|
:destroy,
|
||||||
:rebase,
|
:rebase,
|
||||||
:discussions,
|
:discussions
|
||||||
:description_diff
|
|
||||||
]
|
]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
|
|
@ -26,7 +26,6 @@ module Git
|
||||||
enqueue_detect_repository_languages
|
enqueue_detect_repository_languages
|
||||||
|
|
||||||
execute_related_hooks
|
execute_related_hooks
|
||||||
perform_housekeeping
|
|
||||||
|
|
||||||
stop_environments
|
stop_environments
|
||||||
unlock_artifacts
|
unlock_artifacts
|
||||||
|
@ -71,13 +70,6 @@ module Git
|
||||||
BranchHooksService.new(project, current_user, params).execute
|
BranchHooksService.new(project, current_user, params).execute
|
||||||
end
|
end
|
||||||
|
|
||||||
def perform_housekeeping
|
|
||||||
housekeeping = Repositories::HousekeepingService.new(project)
|
|
||||||
housekeeping.increment!
|
|
||||||
housekeeping.execute if housekeeping.needed?
|
|
||||||
rescue Repositories::HousekeepingService::LeaseTaken
|
|
||||||
end
|
|
||||||
|
|
||||||
def removing_branch?
|
def removing_branch?
|
||||||
Gitlab::Git.blank_ref?(newrev)
|
Gitlab::Git.blank_ref?(newrev)
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,6 +9,8 @@ module Git
|
||||||
|
|
||||||
process_changes_by_action(:branch, changes.branch_changes)
|
process_changes_by_action(:branch, changes.branch_changes)
|
||||||
process_changes_by_action(:tag, changes.tag_changes)
|
process_changes_by_action(:tag, changes.tag_changes)
|
||||||
|
|
||||||
|
perform_housekeeping
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -83,5 +85,12 @@ module Git
|
||||||
|
|
||||||
MergeRequests::PushedBranchesService.new(project: project, current_user: current_user, params: { changes: changes }).execute
|
MergeRequests::PushedBranchesService.new(project: project, current_user: current_user, params: { changes: changes }).execute
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def perform_housekeeping
|
||||||
|
housekeeping = Repositories::HousekeepingService.new(project)
|
||||||
|
housekeeping.increment!
|
||||||
|
housekeeping.execute if housekeeping.needed?
|
||||||
|
rescue Repositories::HousekeepingService::LeaseTaken
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
- if project.archived
|
- if project.archived
|
||||||
%span.badge.badge-warning.badge-pill.gl-badge.md= _('archived')
|
= gl_badge_tag _('archived'), variant: :warning, size: :md
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
%ul.content-list.all-branches
|
%ul.content-list.all-branches
|
||||||
- @branches.each do |branch|
|
- @branches.each do |branch|
|
||||||
= render "projects/branches/branch", branch: branch, merged: @merged_branch_names.include?(branch.name), commit_status: @branch_pipeline_statuses[branch.name], show_commit_status: @branch_pipeline_statuses.any?
|
= render "projects/branches/branch", branch: branch, merged: @merged_branch_names.include?(branch.name), commit_status: @branch_pipeline_statuses[branch.name], show_commit_status: @branch_pipeline_statuses.any?
|
||||||
- if Feature.enabled?(:branches_pagination_without_count, @project, default_enabled: :yaml)
|
- if Feature.enabled?(:branch_list_keyset_pagination, @project, default_enabled: :yaml)
|
||||||
= render('kaminari/gitlab/without_count', previous_path: @prev_path, next_path: @next_path)
|
= render('kaminari/gitlab/without_count', previous_path: @prev_path, next_path: @next_path)
|
||||||
- else
|
- else
|
||||||
= paginate @branches, theme: 'gitlab'
|
= paginate @branches, theme: 'gitlab'
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
= form.label :enabled, class: 'form-check-label' do
|
= form.label :enabled, class: 'form-check-label' do
|
||||||
%strong= s_('CICD|Default to Auto DevOps pipeline')
|
%strong= s_('CICD|Default to Auto DevOps pipeline')
|
||||||
- if auto_devops_enabled
|
- if auto_devops_enabled
|
||||||
%span.badge.badge-info.js-instance-default-badge= badge_for_auto_devops_scope(@project)
|
= gl_badge_tag badge_for_auto_devops_scope(@project), { variant: :info }, { class: 'js-instance-default-badge'}
|
||||||
.form-text.text-muted
|
.form-text.text-muted
|
||||||
= s_('CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found.')
|
= s_('CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found.')
|
||||||
= link_to _('Learn more.'), help_page_path('topics/autodevops/index.md'), target: '_blank'
|
= link_to _('Learn more.'), help_page_path('topics/autodevops/index.md'), target: '_blank'
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
---
|
|
||||||
name: branches_pagination_without_count
|
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50759
|
|
||||||
rollout_issue_url:
|
|
||||||
milestone: '13.9'
|
|
||||||
type: development
|
|
||||||
group: group::source code
|
|
||||||
default_enabled: false
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
data_category: optional
|
||||||
|
key_path: redis_hll_counters.testing.users_expanding_testing_license_compliance_report_monthly
|
||||||
|
description: Count of expanding the license compliance widget
|
||||||
|
product_section: sec
|
||||||
|
product_stage: secure
|
||||||
|
product_group: group::static analysis
|
||||||
|
product_category: dependency_scanning
|
||||||
|
value_type: number
|
||||||
|
status: active
|
||||||
|
milestone: '14.6'
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75643
|
||||||
|
time_frame: 28d
|
||||||
|
data_source: redis_hll
|
||||||
|
instrumentation_class: RedisHLLMetric
|
||||||
|
options:
|
||||||
|
events:
|
||||||
|
- users_expanding_testing_license_compliance_report
|
||||||
|
distribution:
|
||||||
|
- ce
|
||||||
|
- ee
|
||||||
|
tier:
|
||||||
|
- free
|
||||||
|
- premium
|
||||||
|
- ultimate
|
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
data_category: optional
|
||||||
|
key_path: redis_hll_counters.testing.users_visiting_testing_license_compliance_full_report_monthly
|
||||||
|
description: Count of visiting the license compliance full report
|
||||||
|
product_section: sec
|
||||||
|
product_stage: secure
|
||||||
|
product_group: group::static analysis
|
||||||
|
product_category: dependency_scanning
|
||||||
|
value_type: number
|
||||||
|
status: active
|
||||||
|
milestone: '14.6'
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75643
|
||||||
|
time_frame: 28d
|
||||||
|
data_source: redis_hll
|
||||||
|
instrumentation_class: RedisHLLMetric
|
||||||
|
options:
|
||||||
|
events:
|
||||||
|
- users_visiting_testing_license_compliance_full_report
|
||||||
|
distribution:
|
||||||
|
- ce
|
||||||
|
- ee
|
||||||
|
tier:
|
||||||
|
- free
|
||||||
|
- premium
|
||||||
|
- ultimate
|
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
data_category: optional
|
||||||
|
key_path: redis_hll_counters.testing.users_visiting_testing_manage_license_compliance_monthly
|
||||||
|
description: Count of visiting the manage license compliance page
|
||||||
|
product_section: sec
|
||||||
|
product_stage: secure
|
||||||
|
product_group: group::static analysis
|
||||||
|
product_category: dependency_scanning
|
||||||
|
value_type: number
|
||||||
|
status: active
|
||||||
|
milestone: '14.6'
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75643
|
||||||
|
time_frame: 28d
|
||||||
|
data_source: redis_hll
|
||||||
|
instrumentation_class: RedisHLLMetric
|
||||||
|
options:
|
||||||
|
events:
|
||||||
|
- users_visiting_testing_manage_license_compliance
|
||||||
|
distribution:
|
||||||
|
- ce
|
||||||
|
- ee
|
||||||
|
tier:
|
||||||
|
- free
|
||||||
|
- premium
|
||||||
|
- ultimate
|
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
data_category: optional
|
||||||
|
key_path: redis_hll_counters.testing.users_expanding_testing_license_compliance_report_weekly
|
||||||
|
description: Count of expanding the license compliance widget
|
||||||
|
product_section: sec
|
||||||
|
product_stage: secure
|
||||||
|
product_group: group::static analysis
|
||||||
|
product_category: dependency_scanning
|
||||||
|
value_type: number
|
||||||
|
status: active
|
||||||
|
milestone: '14.6'
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75643
|
||||||
|
time_frame: 7d
|
||||||
|
data_source: redis_hll
|
||||||
|
instrumentation_class: RedisHLLMetric
|
||||||
|
options:
|
||||||
|
events:
|
||||||
|
- users_expanding_testing_license_compliance_report
|
||||||
|
distribution:
|
||||||
|
- ce
|
||||||
|
- ee
|
||||||
|
tier:
|
||||||
|
- free
|
||||||
|
- premium
|
||||||
|
- ultimate
|
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
data_category: optional
|
||||||
|
key_path: redis_hll_counters.testing.users_visiting_testing_license_compliance_full_report_weekly
|
||||||
|
description: Count of visiting the license compliance full report
|
||||||
|
product_section: sec
|
||||||
|
product_stage: secure
|
||||||
|
product_group: group::static analysis
|
||||||
|
product_category: dependency_scanning
|
||||||
|
value_type: number
|
||||||
|
status: active
|
||||||
|
milestone: '14.6'
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75643
|
||||||
|
time_frame: 7d
|
||||||
|
data_source: redis_hll
|
||||||
|
instrumentation_class: RedisHLLMetric
|
||||||
|
options:
|
||||||
|
events:
|
||||||
|
- users_visiting_testing_license_compliance_full_report
|
||||||
|
distribution:
|
||||||
|
- ce
|
||||||
|
- ee
|
||||||
|
tier:
|
||||||
|
- free
|
||||||
|
- premium
|
||||||
|
- ultimate
|
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
data_category: optional
|
||||||
|
key_path: redis_hll_counters.testing.users_visiting_testing_manage_license_compliance_weekly
|
||||||
|
description: Count of visiting the manage license compliance page
|
||||||
|
product_section: sec
|
||||||
|
product_stage: secure
|
||||||
|
product_group: group::static analysis
|
||||||
|
product_category: dependency_scanning
|
||||||
|
value_type: number
|
||||||
|
status: active
|
||||||
|
milestone: '14.6'
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75643
|
||||||
|
time_frame: 7d
|
||||||
|
data_source: redis_hll
|
||||||
|
instrumentation_class: RedisHLLMetric
|
||||||
|
options:
|
||||||
|
events:
|
||||||
|
- users_visiting_testing_manage_license_compliance
|
||||||
|
distribution:
|
||||||
|
- ce
|
||||||
|
- ee
|
||||||
|
tier:
|
||||||
|
- free
|
||||||
|
- premium
|
||||||
|
- ultimate
|
|
@ -56,7 +56,7 @@ In `config/gitlab.yml`:
|
||||||
## Storing LFS objects in remote object storage
|
## Storing LFS objects in remote object storage
|
||||||
|
|
||||||
You can store LFS objects in remote object storage. This allows you
|
You can store LFS objects in remote object storage. This allows you
|
||||||
to offload reads and writes to the local disk, and free up disk space significantly.
|
to reduce reads and writes to the local disk, and free up disk space significantly.
|
||||||
GitLab is tightly integrated with `Fog`, so you can refer to its [documentation](http://fog.io/about/provider_documentation.html)
|
GitLab is tightly integrated with `Fog`, so you can refer to its [documentation](http://fog.io/about/provider_documentation.html)
|
||||||
to check which storage services can be integrated with GitLab.
|
to check which storage services can be integrated with GitLab.
|
||||||
You can also use external object storage in a private local network. For example,
|
You can also use external object storage in a private local network. For example,
|
||||||
|
@ -98,32 +98,6 @@ See [the available connection settings for different providers](../object_storag
|
||||||
|
|
||||||
Here is a configuration example with S3.
|
Here is a configuration example with S3.
|
||||||
|
|
||||||
### Manual uploading to an object storage
|
|
||||||
|
|
||||||
There are two ways to manually do the same thing as automatic uploading (described above).
|
|
||||||
|
|
||||||
**Option 1: Rake task**
|
|
||||||
|
|
||||||
```shell
|
|
||||||
gitlab-rake gitlab:lfs:migrate
|
|
||||||
```
|
|
||||||
|
|
||||||
**Option 2: Rails console**
|
|
||||||
|
|
||||||
Log into the Rails console:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
sudo gitlab-rails console
|
|
||||||
```
|
|
||||||
|
|
||||||
Upload LFS files manually
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
LfsObject.where(file_store: [nil, 1]).find_each do |lfs_object|
|
|
||||||
lfs_object.file.migrate!(ObjectStorage::Store::REMOTE) if lfs_object.file.file.exists?
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
### S3 for Omnibus installations
|
### S3 for Omnibus installations
|
||||||
|
|
||||||
On Omnibus GitLab installations, the settings are prefixed by `lfs_object_store_`:
|
On Omnibus GitLab installations, the settings are prefixed by `lfs_object_store_`:
|
||||||
|
@ -146,32 +120,10 @@ On Omnibus GitLab installations, the settings are prefixed by `lfs_object_store_
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Save the file, and then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
|
1. Save the file, and then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
|
||||||
1. Migrate any existing local LFS objects to the object storage:
|
1. [Migrate any existing local LFS objects to the object storage](#migrating-to-object-storage).
|
||||||
|
New LFS objects
|
||||||
```shell
|
|
||||||
gitlab-rake gitlab:lfs:migrate
|
|
||||||
```
|
|
||||||
|
|
||||||
This migrates existing LFS objects to object storage. New LFS objects
|
|
||||||
are forwarded to object storage unless
|
are forwarded to object storage unless
|
||||||
`gitlab_rails['lfs_object_store_background_upload']` and `gitlab_rails['lfs_object_store_direct_upload']` is set to `false`.
|
`gitlab_rails['lfs_object_store_background_upload']` and `gitlab_rails['lfs_object_store_direct_upload']` is set to `false`.
|
||||||
1. Optional. Verify all files migrated properly.
|
|
||||||
From [PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database)
|
|
||||||
(`sudo gitlab-psql -d gitlabhq_production`) verify `objectstg` below (where `file_store=2`) has count of all artifacts:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
gitlabhq_production=# SELECT count(*) AS total, sum(case when file_store = '1' then 1 else 0 end) AS filesystem, sum(case when file_store = '2' then 1 else 0 end) AS objectstg FROM lfs_objects;
|
|
||||||
|
|
||||||
total | filesystem | objectstg
|
|
||||||
------+------------+-----------
|
|
||||||
2409 | 0 | 2409
|
|
||||||
```
|
|
||||||
|
|
||||||
Verify no files on disk in `artifacts` folder:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
sudo find /var/opt/gitlab/gitlab-rails/shared/lfs-objects -type f | grep -v tmp/cache | wc -l
|
|
||||||
```
|
|
||||||
|
|
||||||
### S3 for installations from source
|
### S3 for installations from source
|
||||||
|
|
||||||
|
@ -199,31 +151,68 @@ For source installations the settings are nested under `lfs:` and then
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Save the file, and then [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
|
1. Save the file, and then [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
|
||||||
1. Migrate any existing local LFS objects to the object storage:
|
1. [Migrate any existing local LFS objects to the object storage](#migrating-to-object-storage).
|
||||||
|
New LFS objects
|
||||||
|
are forwarded to object storage unless
|
||||||
|
`background_upload` and `direct_upload` is set to `false`.
|
||||||
|
|
||||||
```shell
|
### Migrating to object storage
|
||||||
sudo -u git -H bundle exec rake gitlab:lfs:migrate RAILS_ENV=production
|
|
||||||
```
|
|
||||||
|
|
||||||
This migrates existing LFS objects to object storage. New LFS objects
|
**Option 1: Rake task**
|
||||||
are forwarded to object storage unless `background_upload` and `direct_upload` is set to
|
|
||||||
`false`.
|
|
||||||
1. Optional. Verify all files migrated properly.
|
|
||||||
From PostgreSQL console (`sudo -u git -H psql -d gitlabhq_production`) verify `objectstg` below (where `file_store=2`) has count of all artifacts:
|
|
||||||
|
|
||||||
```shell
|
After [configuring the object storage](#storing-lfs-objects-in-remote-object-storage), use the following task to
|
||||||
gitlabhq_production=# SELECT count(*) AS total, sum(case when file_store = '1' then 1 else 0 end) AS filesystem, sum(case when file_store = '2' then 1 else 0 end) AS objectstg FROM lfs_objects;
|
migrate existing LFS objects from the local storage to the remote storage.
|
||||||
|
The processing is done in a background worker and requires **no downtime**.
|
||||||
|
|
||||||
total | filesystem | objectstg
|
For Omnibus GitLab:
|
||||||
------+------------+-----------
|
|
||||||
2409 | 0 | 2409
|
|
||||||
```
|
|
||||||
|
|
||||||
Verify no files on disk in `artifacts` folder:
|
```shell
|
||||||
|
sudo gitlab-rake "gitlab:lfs:migrate"
|
||||||
|
```
|
||||||
|
|
||||||
```shell
|
For installations from source:
|
||||||
sudo find /var/opt/gitlab/gitlab-rails/shared/lfs-objects -type f | grep -v tmp/cache | wc -l
|
|
||||||
```
|
```shell
|
||||||
|
RAILS_ENV=production sudo -u git -H bundle exec rake gitlab:lfs:migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
You can optionally track progress and verify that all packages migrated successfully using the
|
||||||
|
[PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database):
|
||||||
|
|
||||||
|
- `sudo gitlab-rails dbconsole` for Omnibus GitLab instances.
|
||||||
|
- `sudo -u git -H psql -d gitlabhq_production` for source-installed instances.
|
||||||
|
|
||||||
|
Verify `objectstg` below (where `store=2`) has count of all LFS objects:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
gitlabhq_production=# SELECT count(*) AS total, sum(case when file_store = '1' then 1 else 0 end) AS filesystem, sum(case when file_store = '2' then 1 else 0 end) AS objectstg FROM lfs_objects;
|
||||||
|
|
||||||
|
total | filesystem | objectstg
|
||||||
|
------+------------+-----------
|
||||||
|
2409 | 0 | 2409
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify that there are no files on disk in the `objects` folder:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sudo find /var/opt/gitlab/gitlab-rails/shared/lfs-objects -type f | grep -v tmp | wc -l
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option 2: Rails console**
|
||||||
|
|
||||||
|
Log into the Rails console:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sudo gitlab-rails console
|
||||||
|
```
|
||||||
|
|
||||||
|
Upload LFS files manually
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
LfsObject.where(file_store: [nil, 1]).find_each do |lfs_object|
|
||||||
|
lfs_object.file.migrate!(ObjectStorage::Store::REMOTE) if lfs_object.file.file.exists?
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
### Migrating back to local storage
|
### Migrating back to local storage
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,28 @@ gitlab-rake "gitlab:uploads:migrate:all"
|
||||||
sudo RAILS_ENV=production -u git -H bundle exec rake gitlab:uploads:migrate:all
|
sudo RAILS_ENV=production -u git -H bundle exec rake gitlab:uploads:migrate:all
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can optionally track progress and verify that all packages migrated successfully using the
|
||||||
|
[PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database):
|
||||||
|
|
||||||
|
- `sudo gitlab-rails dbconsole` for Omnibus GitLab instances.
|
||||||
|
- `sudo -u git -H psql -d gitlabhq_production` for source-installed instances.
|
||||||
|
|
||||||
|
Verify `objectstg` below (where `store=2`) has count of all artifacts:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
gitlabhq_production=# SELECT count(*) AS total, sum(case when store = '1' then 1 else 0 end) AS filesystem, sum(case when store = '2' then 1 else 0 end) AS objectstg FROM uploads;
|
||||||
|
|
||||||
|
total | filesystem | objectstg
|
||||||
|
------+------------+-----------
|
||||||
|
2409 | 0 | 2409
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify that there are no files on disk in the `uploads` folder:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sudo find /var/opt/gitlab/gitlab-rails/uploads -type f | grep -v tmp | wc -l
|
||||||
|
```
|
||||||
|
|
||||||
### Individual Rake tasks
|
### Individual Rake tasks
|
||||||
|
|
||||||
If you already ran the [all-in-one Rake task](#all-in-one-rake-task), there is no need to run these
|
If you already ran the [all-in-one Rake task](#all-in-one-rake-task), there is no need to run these
|
||||||
|
|
|
@ -130,6 +130,28 @@ For GitLab 13.8 and earlier versions, you can use a workaround for the Rake task
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can optionally track progress and verify that all packages migrated successfully using the
|
||||||
|
[PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database):
|
||||||
|
|
||||||
|
- `sudo gitlab-rails dbconsole` for Omnibus GitLab instances.
|
||||||
|
- `sudo -u git -H psql -d gitlabhq_production` for source-installed instances.
|
||||||
|
|
||||||
|
Verify `objectstg` below (where `store=2`) has count of all states:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
gitlabhq_production=# SELECT count(*) AS total, sum(case when store = '1' then 1 else 0 end) AS filesystem, sum(case when store = '2' then 1 else 0 end) AS objectstg FROM terraform_states;
|
||||||
|
|
||||||
|
total | filesystem | objectstg
|
||||||
|
------+------------+-----------
|
||||||
|
15 | 0 | 15
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify that there are no files on disk in the `terraform_state` folder:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sudo find /var/opt/gitlab/gitlab-rails/shared/terraform_state -type f | wc -l
|
||||||
|
```
|
||||||
|
|
||||||
### S3-compatible connection settings
|
### S3-compatible connection settings
|
||||||
|
|
||||||
See [the available connection settings for different providers](object_storage.md#connection-settings).
|
See [the available connection settings for different providers](object_storage.md#connection-settings).
|
||||||
|
@ -162,11 +184,7 @@ See [the available connection settings for different providers](object_storage.m
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
|
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
|
||||||
1. Migrate any existing local states to the object storage (GitLab 13.9 and later):
|
1. [Migrate any existing local states to the object storage](#migrate-to-object-storage)
|
||||||
|
|
||||||
```shell
|
|
||||||
gitlab-rake gitlab:terraform_states:migrate
|
|
||||||
```
|
|
||||||
|
|
||||||
**In installations from source:**
|
**In installations from source:**
|
||||||
|
|
||||||
|
@ -187,8 +205,4 @@ See [the available connection settings for different providers](object_storage.m
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
|
1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
|
||||||
1. Migrate any existing local states to the object storage (GitLab 13.9 and later):
|
1. [Migrate any existing local states to the object storage](#migrate-to-object-storage)
|
||||||
|
|
||||||
```shell
|
|
||||||
sudo -u git -H bundle exec rake gitlab:terraform_states:migrate RAILS_ENV=production
|
|
||||||
```
|
|
||||||
|
|
|
@ -106,24 +106,7 @@ _The uploads are stored by default in
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
|
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
|
||||||
1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate` Rake task](raketasks/uploads/migrate.md).
|
1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
|
||||||
1. Optional: Verify all files migrated properly.
|
|
||||||
From [PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database)
|
|
||||||
(`sudo gitlab-psql -d gitlabhq_production`) verify `objectstg` below (where `store=2`) has count of all artifacts:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
gitlabhq_production=# SELECT count(*) AS total, sum(case when store = '1' then 1 else 0 end) AS filesystem, sum(case when store = '2' then 1 else 0 end) AS objectstg FROM uploads;
|
|
||||||
|
|
||||||
total | filesystem | objectstg
|
|
||||||
------+------------+-----------
|
|
||||||
2409 | 0 | 2409
|
|
||||||
```
|
|
||||||
|
|
||||||
Verify no files on disk in `artifacts` folder:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
sudo find /var/opt/gitlab/gitlab-rails/uploads -type f | grep -v tmp | wc -l
|
|
||||||
```
|
|
||||||
|
|
||||||
**In installations from source:**
|
**In installations from source:**
|
||||||
|
|
||||||
|
@ -147,22 +130,6 @@ _The uploads are stored by default in
|
||||||
|
|
||||||
1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
|
1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
|
||||||
1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
|
1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
|
||||||
1. Optional: Verify all files migrated properly.
|
|
||||||
From PostgreSQL console (`sudo -u git -H psql -d gitlabhq_production`) verify `objectstg` below (where `file_store=2`) has count of all artifacts:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
gitlabhq_production=# SELECT count(*) AS total, sum(case when store = '1' then 1 else 0 end) AS filesystem, sum(case when store = '2' then 1 else 0 end) AS objectstg FROM uploads;
|
|
||||||
|
|
||||||
total | filesystem | objectstg
|
|
||||||
------+------------+-----------
|
|
||||||
2409 | 0 | 2409
|
|
||||||
```
|
|
||||||
|
|
||||||
Verify no files on disk in `artifacts` folder:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
sudo find /var/opt/gitlab/gitlab-rails/uploads -type f | grep -v tmp | wc -l
|
|
||||||
```
|
|
||||||
|
|
||||||
#### OpenStack example
|
#### OpenStack example
|
||||||
|
|
||||||
|
@ -189,23 +156,6 @@ _The uploads are stored by default in
|
||||||
|
|
||||||
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
|
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
|
||||||
1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
|
1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
|
||||||
1. Optional: Verify all files migrated properly.
|
|
||||||
From [PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database)
|
|
||||||
(`sudo gitlab-psql -d gitlabhq_production`) verify `objectstg` below (where `store=2`) has count of all artifacts:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
gitlabhq_production=# SELECT count(*) AS total, sum(case when store = '1' then 1 else 0 end) AS filesystem, sum(case when store = '2' then 1 else 0 end) AS objectstg FROM uploads;
|
|
||||||
|
|
||||||
total | filesystem | objectstg
|
|
||||||
------+------------+-----------
|
|
||||||
2409 | 0 | 2409
|
|
||||||
```
|
|
||||||
|
|
||||||
Verify no files on disk in `artifacts` folder:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
sudo find /var/opt/gitlab/gitlab-rails/uploads -type f | grep -v tmp | wc -l
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -237,19 +187,3 @@ _The uploads are stored by default in
|
||||||
|
|
||||||
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
|
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
|
||||||
1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
|
1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
|
||||||
1. Optional: Verify all files migrated properly.
|
|
||||||
From PostgreSQL console (`sudo -u git -H psql -d gitlabhq_production`) verify `objectstg` below (where `file_store=2`) has count of all artifacts:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
gitlabhq_production=# SELECT count(*) AS total, sum(case when store = '1' then 1 else 0 end) AS filesystem, sum(case when store = '2' then 1 else 0 end) AS objectstg FROM uploads;
|
|
||||||
|
|
||||||
total | filesystem | objectstg
|
|
||||||
------+------------+-----------
|
|
||||||
2409 | 0 | 2409
|
|
||||||
```
|
|
||||||
|
|
||||||
Verify no files on disk in `artifacts` folder:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
sudo find /var/opt/gitlab/gitlab-rails/uploads -type f | grep -v tmp | wc -l
|
|
||||||
```
|
|
||||||
|
|
|
@ -48,20 +48,9 @@ To make sure you can easily run the most recent stable release, we are working
|
||||||
hard to keep the update process simple and reliable.
|
hard to keep the update process simple and reliable.
|
||||||
|
|
||||||
If you are unable to follow our monthly release cycle, there are a couple of
|
If you are unable to follow our monthly release cycle, there are a couple of
|
||||||
cases you need to consider.
|
cases you need to consider. Follow the
|
||||||
|
[upgrade paths guide](../update/index.md#upgrade-paths) to safely upgrade
|
||||||
It is considered safe to jump between patch versions and minor versions within
|
between versions.
|
||||||
one major version. For example, it is safe to:
|
|
||||||
|
|
||||||
- Upgrade the *minor* version. For example:
|
|
||||||
|
|
||||||
- `13.7.5` -> `13.10.5`
|
|
||||||
- `12.3.4` -> `12.10.11`
|
|
||||||
|
|
||||||
- Upgrade the *patch* version. For example:
|
|
||||||
|
|
||||||
- `13.0.4` -> `13.0.12`
|
|
||||||
- `12.10.1` -> `12.10.8`
|
|
||||||
|
|
||||||
NOTE:
|
NOTE:
|
||||||
Version specific changes in Omnibus GitLab Linux packages can be found in [the Omnibus GitLab documentation](../update/package/index.md#version-specific-changes).
|
Version specific changes in Omnibus GitLab Linux packages can be found in [the Omnibus GitLab documentation](../update/package/index.md#version-specific-changes).
|
||||||
|
|
|
@ -45,7 +45,6 @@ module Gitlab
|
||||||
end
|
end
|
||||||
|
|
||||||
def overwrite_headers(message, signed_email)
|
def overwrite_headers(message, signed_email)
|
||||||
message.content_disposition = signed_email.content_disposition
|
|
||||||
message.content_transfer_encoding = signed_email.content_transfer_encoding
|
message.content_transfer_encoding = signed_email.content_transfer_encoding
|
||||||
message.content_type = signed_email.content_type
|
message.content_type = signed_email.content_type
|
||||||
end
|
end
|
||||||
|
|
|
@ -355,6 +355,19 @@
|
||||||
category: testing
|
category: testing
|
||||||
aggregation: weekly
|
aggregation: weekly
|
||||||
feature_flag: users_expanding_widgets_usage_data
|
feature_flag: users_expanding_widgets_usage_data
|
||||||
|
- name: users_expanding_testing_license_compliance_report
|
||||||
|
redis_slot: testing
|
||||||
|
category: testing
|
||||||
|
aggregation: weekly
|
||||||
|
feature_flag: users_expanding_widgets_usage_data
|
||||||
|
- name: users_visiting_testing_license_compliance_full_report
|
||||||
|
redis_slot: testing
|
||||||
|
category: testing
|
||||||
|
aggregation: weekly
|
||||||
|
- name: users_visiting_testing_manage_license_compliance
|
||||||
|
redis_slot: testing
|
||||||
|
category: testing
|
||||||
|
aggregation: weekly
|
||||||
# Container Security - Network Policies
|
# Container Security - Network Policies
|
||||||
- name: clusters_using_network_policies_ui
|
- name: clusters_using_network_policies_ui
|
||||||
redis_slot: network_policies
|
redis_slot: network_policies
|
||||||
|
|
|
@ -6785,7 +6785,7 @@ msgstr ""
|
||||||
msgid "Checkout"
|
msgid "Checkout"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Checkout|$%{selectedPlanPrice} per 10 GB storage per pack"
|
msgid "Checkout|$%{selectedPlanPrice} per 10 GB storage pack per year"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Checkout|$%{selectedPlanPrice} per pack of 1,000 minutes"
|
msgid "Checkout|$%{selectedPlanPrice} per pack of 1,000 minutes"
|
||||||
|
|
|
@ -28,7 +28,7 @@ describe('Blob viewer', () => {
|
||||||
loadFixtures('blob/show_readme.html');
|
loadFixtures('blob/show_readme.html');
|
||||||
$('#modal-upload-blob').remove();
|
$('#modal-upload-blob').remove();
|
||||||
|
|
||||||
mock.onGet(/blob\/master\/README\.md/).reply(200, {
|
mock.onGet(/blob\/.+\/README\.md/).reply(200, {
|
||||||
html: '<div>testing</div>',
|
html: '<div>testing</div>',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ RSpec.describe Projects::BlobController, '(JavaScript fixtures)', type: :control
|
||||||
get(:show, params: {
|
get(:show, params: {
|
||||||
namespace_id: project.namespace,
|
namespace_id: project.namespace,
|
||||||
project_id: project,
|
project_id: project,
|
||||||
id: 'master/README.md'
|
id: "#{project.default_branch}/README.md"
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(response).to be_successful
|
expect(response).to be_successful
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { mount } from '@vue/test-utils';
|
||||||
import { stubComponent } from 'helpers/stub_component';
|
import { stubComponent } from 'helpers/stub_component';
|
||||||
import { TEST_HOST } from 'helpers/test_constants';
|
import { TEST_HOST } from 'helpers/test_constants';
|
||||||
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
||||||
import DeleteLabelModal from '~/vue_shared/components/delete_label_modal.vue';
|
import DeleteLabelModal from '~/labels/components/delete_label_modal.vue';
|
||||||
|
|
||||||
const MOCK_MODAL_DATA = {
|
const MOCK_MODAL_DATA = {
|
||||||
labelName: 'label 1',
|
labelName: 'label 1',
|
||||||
|
@ -11,7 +11,7 @@ const MOCK_MODAL_DATA = {
|
||||||
destroyPath: `${TEST_HOST}/1`,
|
destroyPath: `${TEST_HOST}/1`,
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('vue_shared/components/delete_label_modal', () => {
|
describe('~/labels/components/delete_label_modal', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
|
|
||||||
const createComponent = () => {
|
const createComponent = () => {
|
|
@ -2,8 +2,8 @@ import Vue from 'vue';
|
||||||
import { TEST_HOST } from 'helpers/test_constants';
|
import { TEST_HOST } from 'helpers/test_constants';
|
||||||
import mountComponent from 'helpers/vue_mount_component_helper';
|
import mountComponent from 'helpers/vue_mount_component_helper';
|
||||||
import axios from '~/lib/utils/axios_utils';
|
import axios from '~/lib/utils/axios_utils';
|
||||||
import promoteLabelModal from '~/pages/projects/labels/components/promote_label_modal.vue';
|
import promoteLabelModal from '~/labels/components/promote_label_modal.vue';
|
||||||
import eventHub from '~/pages/projects/labels/event_hub';
|
import eventHub from '~/labels/event_hub';
|
||||||
|
|
||||||
describe('Promote label modal', () => {
|
describe('Promote label modal', () => {
|
||||||
let vm;
|
let vm;
|
|
@ -1,5 +1,5 @@
|
||||||
import { TEST_HOST } from 'helpers/test_constants';
|
import { TEST_HOST } from 'helpers/test_constants';
|
||||||
import initDeleteLabelModal from '~/labels/delete_label_modal';
|
import { initDeleteLabelModal } from '~/labels';
|
||||||
|
|
||||||
describe('DeleteLabelModal', () => {
|
describe('DeleteLabelModal', () => {
|
||||||
const buttons = [
|
const buttons = [
|
||||||
|
|
|
@ -124,19 +124,7 @@ describe('DropdownContent', () => {
|
||||||
expect(wrapper.emitted('setLabels')).toEqual([[[updatedLabel]]]);
|
expect(wrapper.emitted('setLabels')).toEqual([[[updatedLabel]]]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not render header on standalone variant', () => {
|
it('renders header', () => {
|
||||||
createComponent({ props: { variant: DropdownVariant.Standalone } });
|
|
||||||
|
|
||||||
expect(findDropdownHeader().exists()).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders header on embedded variant', () => {
|
|
||||||
createComponent({ props: { variant: DropdownVariant.Embedded } });
|
|
||||||
|
|
||||||
expect(findDropdownHeader().exists()).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders header on sidebar variant', () => {
|
|
||||||
createComponent();
|
createComponent();
|
||||||
|
|
||||||
expect(findDropdownHeader().exists()).toBe(true);
|
expect(findDropdownHeader().exists()).toBe(true);
|
||||||
|
|
|
@ -9,6 +9,7 @@ describe('DropdownHeader', () => {
|
||||||
const createComponent = ({
|
const createComponent = ({
|
||||||
showDropdownContentsCreateView = false,
|
showDropdownContentsCreateView = false,
|
||||||
labelsFetchInProgress = false,
|
labelsFetchInProgress = false,
|
||||||
|
isStandalone = false,
|
||||||
} = {}) => {
|
} = {}) => {
|
||||||
wrapper = extendedWrapper(
|
wrapper = extendedWrapper(
|
||||||
shallowMount(DropdownHeader, {
|
shallowMount(DropdownHeader, {
|
||||||
|
@ -18,6 +19,7 @@ describe('DropdownHeader', () => {
|
||||||
labelsCreateTitle: 'Create label',
|
labelsCreateTitle: 'Create label',
|
||||||
labelsListTitle: 'Select label',
|
labelsListTitle: 'Select label',
|
||||||
searchKey: '',
|
searchKey: '',
|
||||||
|
isStandalone,
|
||||||
},
|
},
|
||||||
stubs: {
|
stubs: {
|
||||||
GlSearchBoxByType,
|
GlSearchBoxByType,
|
||||||
|
@ -32,6 +34,7 @@ describe('DropdownHeader', () => {
|
||||||
|
|
||||||
const findSearchInput = () => wrapper.findComponent(GlSearchBoxByType);
|
const findSearchInput = () => wrapper.findComponent(GlSearchBoxByType);
|
||||||
const findGoBackButton = () => wrapper.findByTestId('go-back-button');
|
const findGoBackButton = () => wrapper.findByTestId('go-back-button');
|
||||||
|
const findDropdownTitle = () => wrapper.findByTestId('dropdown-header-title');
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
createComponent();
|
createComponent();
|
||||||
|
@ -72,4 +75,18 @@ describe('DropdownHeader', () => {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Standalone variant', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
createComponent({ isStandalone: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders search input', () => {
|
||||||
|
expect(findSearchInput().exists()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not render title', async () => {
|
||||||
|
expect(findDropdownTitle().exists()).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -75,9 +75,9 @@ describe('LabelsSelectRoot', () => {
|
||||||
wrapper.destroy();
|
wrapper.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders component with classes `labels-select-wrapper position-relative`', () => {
|
it('renders component with classes `labels-select-wrapper gl-relative`', () => {
|
||||||
createComponent();
|
createComponent();
|
||||||
expect(wrapper.classes()).toEqual(['labels-select-wrapper', 'position-relative']);
|
expect(wrapper.classes()).toEqual(['labels-select-wrapper', 'gl-relative']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each`
|
it.each`
|
||||||
|
|
|
@ -50,6 +50,7 @@ RSpec.describe Gitlab::Email::Hook::SmimeSignatureInterceptor do
|
||||||
expect(mail.header['To'].value).to eq('test@example.com')
|
expect(mail.header['To'].value).to eq('test@example.com')
|
||||||
expect(mail.header['From'].value).to eq('info@example.com')
|
expect(mail.header['From'].value).to eq('info@example.com')
|
||||||
expect(mail.header['Content-Type'].value).to match('multipart/signed').and match('protocol="application/x-pkcs7-signature"')
|
expect(mail.header['Content-Type'].value).to match('multipart/signed').and match('protocol="application/x-pkcs7-signature"')
|
||||||
|
expect(mail.header.include?('Content-Disposition')).to eq(false)
|
||||||
|
|
||||||
# verify signature and obtain pkcs7 encoded content
|
# verify signature and obtain pkcs7 encoded content
|
||||||
p7enc = Gitlab::Email::Smime::Signer.verify_signature(
|
p7enc = Gitlab::Email::Smime::Signer.verify_signature(
|
||||||
|
|
|
@ -82,7 +82,7 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
|
||||||
end.new(time_frame: 'all')
|
end.new(time_frame: 'all')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'calculates a correct result' do
|
it 'calculates a correct result', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/348139' do
|
||||||
expect(subject.value).to be_within(Gitlab::Database::PostgresHll::BatchDistinctCounter::ERROR_RATE).percent_of(3)
|
expect(subject.value).to be_within(Gitlab::Database::PostgresHll::BatchDistinctCounter::ERROR_RATE).percent_of(3)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ RSpec.describe 'Query current user todos' do
|
||||||
QUERY
|
QUERY
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'avoids N+1 queries', :request_store do
|
it 'avoids N+1 queries', :request_store, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338671' do
|
||||||
control = ActiveRecord::QueryRecorder.new { post_graphql(query, current_user: current_user) }
|
control = ActiveRecord::QueryRecorder.new { post_graphql(query, current_user: current_user) }
|
||||||
|
|
||||||
project2 = create(:project)
|
project2 = create(:project)
|
||||||
|
|
|
@ -554,44 +554,6 @@ RSpec.describe Git::BranchPushService, services: true do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "housekeeping", :clean_gitlab_redis_cache, :clean_gitlab_redis_queues, :clean_gitlab_redis_shared_state do
|
|
||||||
let(:housekeeping) { Repositories::HousekeepingService.new(project) }
|
|
||||||
|
|
||||||
before do
|
|
||||||
allow(Repositories::HousekeepingService).to receive(:new).and_return(housekeeping)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'does not perform housekeeping when not needed' do
|
|
||||||
expect(housekeeping).not_to receive(:execute)
|
|
||||||
|
|
||||||
execute_service(project, user, oldrev: oldrev, newrev: newrev, ref: ref)
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when housekeeping is needed' do
|
|
||||||
before do
|
|
||||||
allow(housekeeping).to receive(:needed?).and_return(true)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'performs housekeeping' do
|
|
||||||
expect(housekeeping).to receive(:execute)
|
|
||||||
|
|
||||||
execute_service(project, user, oldrev: oldrev, newrev: newrev, ref: ref)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'does not raise an exception' do
|
|
||||||
allow(housekeeping).to receive(:try_obtain_lease).and_return(false)
|
|
||||||
|
|
||||||
execute_service(project, user, oldrev: oldrev, newrev: newrev, ref: ref)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'increments the push counter' do
|
|
||||||
expect(housekeeping).to receive(:increment!)
|
|
||||||
|
|
||||||
execute_service(project, user, oldrev: oldrev, newrev: newrev, ref: ref)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "CI environments" do
|
describe "CI environments" do
|
||||||
context 'create branch' do
|
context 'create branch' do
|
||||||
let(:oldrev) { blankrev }
|
let(:oldrev) { blankrev }
|
||||||
|
|
|
@ -161,6 +161,50 @@ RSpec.describe Git::ProcessRefChangesService do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "housekeeping", :clean_gitlab_redis_cache, :clean_gitlab_redis_queues, :clean_gitlab_redis_shared_state do
|
||||||
|
let(:housekeeping) { Repositories::HousekeepingService.new(project) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(Repositories::HousekeepingService).to receive(:new).and_return(housekeeping)
|
||||||
|
|
||||||
|
allow(push_service_class)
|
||||||
|
.to receive(:new)
|
||||||
|
.with(project, project.owner, hash_including(execute_project_hooks: true, create_push_event: true))
|
||||||
|
.exactly(changes.count).times
|
||||||
|
.and_return(service)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not perform housekeeping when not needed' do
|
||||||
|
expect(housekeeping).not_to receive(:execute)
|
||||||
|
|
||||||
|
subject.execute
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when housekeeping is needed' do
|
||||||
|
before do
|
||||||
|
allow(housekeeping).to receive(:needed?).and_return(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'performs housekeeping' do
|
||||||
|
expect(housekeeping).to receive(:execute)
|
||||||
|
|
||||||
|
subject.execute
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not raise an exception' do
|
||||||
|
allow(housekeeping).to receive(:try_obtain_lease).and_return(false)
|
||||||
|
|
||||||
|
subject.execute
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'increments the push counter' do
|
||||||
|
expect(housekeeping).to receive(:increment!)
|
||||||
|
|
||||||
|
subject.execute
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'branch changes' do
|
context 'branch changes' do
|
||||||
|
|
Loading…
Reference in New Issue