Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
37974ac0b1
commit
7ad147d6b8
|
|
@ -1 +1 @@
|
|||
4ea88e921af65ba0577c40f8b54830c97adaa56c
|
||||
996add2f4e011cec8e9317912978cf1fa59e66c1
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
import { CodeBlockHighlight as BaseCodeBlockHighlight } from 'tiptap-extensions';
|
||||
|
||||
export default class GlCodeBlockHighlight extends BaseCodeBlockHighlight {
|
||||
get schema() {
|
||||
const baseSchema = super.schema;
|
||||
|
||||
return {
|
||||
...baseSchema,
|
||||
attrs: {
|
||||
params: {
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
parseDOM: [
|
||||
{
|
||||
tag: 'pre',
|
||||
preserveWhitespace: 'full',
|
||||
getAttrs: (node) => {
|
||||
const code = node.querySelector('code');
|
||||
|
||||
if (!code) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
/* `params` is the name of the attribute that
|
||||
prosemirror-markdown uses to extract the language
|
||||
of a codeblock.
|
||||
https://github.com/ProseMirror/prosemirror-markdown/blob/master/src/to_markdown.js#L62
|
||||
*/
|
||||
params: code.getAttribute('lang'),
|
||||
};
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,20 @@
|
|||
import { isFunction, isString } from 'lodash';
|
||||
import { Editor } from 'tiptap';
|
||||
import { Bold, Code } from 'tiptap-extensions';
|
||||
import {
|
||||
Bold,
|
||||
Italic,
|
||||
Code,
|
||||
Link,
|
||||
Image,
|
||||
Heading,
|
||||
Blockquote,
|
||||
HorizontalRule,
|
||||
BulletList,
|
||||
OrderedList,
|
||||
ListItem,
|
||||
} from 'tiptap-extensions';
|
||||
import { PROVIDE_SERIALIZER_OR_RENDERER_ERROR } from '../constants';
|
||||
import CodeBlockHighlight from '../extensions/code_block_highlight';
|
||||
import createMarkdownSerializer from './markdown_serializer';
|
||||
|
||||
const createEditor = async ({ content, renderMarkdown, serializer: customSerializer } = {}) => {
|
||||
|
|
@ -10,7 +23,20 @@ const createEditor = async ({ content, renderMarkdown, serializer: customSeriali
|
|||
}
|
||||
|
||||
const editor = new Editor({
|
||||
extensions: [new Bold(), new Code()],
|
||||
extensions: [
|
||||
new Bold(),
|
||||
new Italic(),
|
||||
new Code(),
|
||||
new Link(),
|
||||
new Image(),
|
||||
new Heading({ levels: [1, 2, 3, 4, 5, 6] }),
|
||||
new Blockquote(),
|
||||
new HorizontalRule(),
|
||||
new BulletList(),
|
||||
new ListItem(),
|
||||
new OrderedList(),
|
||||
new CodeBlockHighlight(),
|
||||
],
|
||||
});
|
||||
const serializer = customSerializer || createMarkdownSerializer({ render: renderMarkdown });
|
||||
|
||||
|
|
|
|||
|
|
@ -60,9 +60,12 @@ const create = ({ render = () => null }) => {
|
|||
// creates a bold alias for the strong mark converter
|
||||
...defaultMarkdownSerializer.marks.strong,
|
||||
},
|
||||
italic: { open: '_', close: '_', mixable: true, expelEnclosingWhitespace: true },
|
||||
});
|
||||
|
||||
return serializer.serialize(document);
|
||||
return serializer.serialize(document, {
|
||||
tightLists: true,
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -184,12 +184,7 @@ export default {
|
|||
'viewDiffsFileByFile',
|
||||
'mrReviews',
|
||||
]),
|
||||
...mapGetters('diffs', [
|
||||
'whichCollapsedTypes',
|
||||
'isParallelView',
|
||||
'currentDiffIndex',
|
||||
'fileCodequalityDiff',
|
||||
]),
|
||||
...mapGetters('diffs', ['whichCollapsedTypes', 'isParallelView', 'currentDiffIndex']),
|
||||
...mapGetters(['isNotesFetched', 'getNoteableData']),
|
||||
diffs() {
|
||||
if (!this.viewDiffsFileByFile) {
|
||||
|
|
@ -287,7 +282,6 @@ export default {
|
|||
endpointMetadata: this.endpointMetadata,
|
||||
endpointBatch: this.endpointBatch,
|
||||
endpointCoverage: this.endpointCoverage,
|
||||
endpointCodequality: this.endpointCodequality,
|
||||
endpointUpdateUser: this.endpointUpdateUser,
|
||||
projectPath: this.projectPath,
|
||||
dismissEndpoint: this.dismissEndpoint,
|
||||
|
|
@ -297,6 +291,10 @@ export default {
|
|||
mrReviews: this.rehydratedMrReviews,
|
||||
});
|
||||
|
||||
if (this.endpointCodequality) {
|
||||
this.setCodequalityEndpoint(this.endpointCodequality);
|
||||
}
|
||||
|
||||
if (this.shouldShow) {
|
||||
this.fetchData();
|
||||
}
|
||||
|
|
@ -341,6 +339,7 @@ export default {
|
|||
...mapActions('diffs', [
|
||||
'moveToNeighboringCommit',
|
||||
'setBaseConfig',
|
||||
'setCodequalityEndpoint',
|
||||
'fetchDiffFilesMeta',
|
||||
'fetchDiffFilesBatch',
|
||||
'fetchCoverageFiles',
|
||||
|
|
@ -532,7 +531,6 @@ export default {
|
|||
:help-page-path="helpPagePath"
|
||||
:can-current-user-fork="canCurrentUserFork"
|
||||
:view-diffs-file-by-file="viewDiffsFileByFile"
|
||||
:codequality-diff="fileCodequalityDiff(file.file_path)"
|
||||
/>
|
||||
<div
|
||||
v-if="showFileByFileNavigation"
|
||||
|
|
|
|||
|
|
@ -67,11 +67,6 @@ export default {
|
|||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
codequalityDiff: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
@ -85,7 +80,7 @@ export default {
|
|||
genericError: GENERIC_ERROR,
|
||||
},
|
||||
computed: {
|
||||
...mapState('diffs', ['currentDiffFileId']),
|
||||
...mapState('diffs', ['currentDiffFileId', 'codequalityDiff']),
|
||||
...mapGetters(['isNotesFetched']),
|
||||
...mapGetters('diffs', ['getDiffFileDiscussions']),
|
||||
viewBlobHref() {
|
||||
|
|
@ -154,7 +149,9 @@ export default {
|
|||
return loggedIn && featureOn;
|
||||
},
|
||||
hasCodequalityChanges() {
|
||||
return this.codequalityDiff.length > 0;
|
||||
return (
|
||||
this.codequalityDiff?.files && this.codequalityDiff?.files[this.file.file_path]?.length > 0
|
||||
);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import Cookies from 'js-cookie';
|
||||
import Visibility from 'visibilityjs';
|
||||
import Vue from 'vue';
|
||||
import { deprecatedCreateFlash as createFlash } from '~/flash';
|
||||
import { diffViewerModes } from '~/ide/constants';
|
||||
|
|
@ -53,15 +52,12 @@ import {
|
|||
prepareLineForRenamedFile,
|
||||
} from './utils';
|
||||
|
||||
let eTagPoll;
|
||||
|
||||
export const setBaseConfig = ({ commit }, options) => {
|
||||
const {
|
||||
endpoint,
|
||||
endpointMetadata,
|
||||
endpointBatch,
|
||||
endpointCoverage,
|
||||
endpointCodequality,
|
||||
endpointUpdateUser,
|
||||
projectPath,
|
||||
dismissEndpoint,
|
||||
|
|
@ -75,7 +71,6 @@ export const setBaseConfig = ({ commit }, options) => {
|
|||
endpointMetadata,
|
||||
endpointBatch,
|
||||
endpointCoverage,
|
||||
endpointCodequality,
|
||||
endpointUpdateUser,
|
||||
projectPath,
|
||||
dismissEndpoint,
|
||||
|
|
@ -238,48 +233,6 @@ export const fetchCoverageFiles = ({ commit, state }) => {
|
|||
coveragePoll.makeRequest();
|
||||
};
|
||||
|
||||
export const clearEtagPoll = () => {
|
||||
eTagPoll = null;
|
||||
};
|
||||
|
||||
export const stopCodequalityPolling = () => {
|
||||
if (eTagPoll) eTagPoll.stop();
|
||||
};
|
||||
|
||||
export const restartCodequalityPolling = () => {
|
||||
if (eTagPoll) eTagPoll.restart();
|
||||
};
|
||||
|
||||
export const fetchCodequality = ({ commit, state, dispatch }) => {
|
||||
eTagPoll = new Poll({
|
||||
resource: {
|
||||
getCodequalityDiffReports: (endpoint) => axios.get(endpoint),
|
||||
},
|
||||
data: state.endpointCodequality,
|
||||
method: 'getCodequalityDiffReports',
|
||||
successCallback: ({ status, data }) => {
|
||||
if (status === httpStatusCodes.OK) {
|
||||
commit(types.SET_CODEQUALITY_DATA, data);
|
||||
|
||||
eTagPoll.stop();
|
||||
}
|
||||
},
|
||||
errorCallback: () => createFlash(__('Something went wrong on our end. Please try again!')),
|
||||
});
|
||||
|
||||
if (!Visibility.hidden()) {
|
||||
eTagPoll.makeRequest();
|
||||
}
|
||||
|
||||
Visibility.change(() => {
|
||||
if (!Visibility.hidden()) {
|
||||
dispatch('restartCodequalityPolling');
|
||||
} else {
|
||||
dispatch('stopCodequalityPolling');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const setHighlightedRow = ({ commit }, lineCode) => {
|
||||
const fileHash = lineCode.split('_')[0];
|
||||
commit(types.SET_HIGHLIGHTED_ROW, lineCode);
|
||||
|
|
|
|||
|
|
@ -135,16 +135,6 @@ export const fileLineCoverage = (state) => (file, line) => {
|
|||
return {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the codequality diff data for a given file
|
||||
* @param {string} filePath
|
||||
* @returns {Array}
|
||||
*/
|
||||
export const fileCodequalityDiff = (state) => (filePath) => {
|
||||
if (!state.codequalityDiff.files || !state.codequalityDiff.files[filePath]) return [];
|
||||
return state.codequalityDiff.files[filePath];
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns index of a currently selected diff in diffFiles
|
||||
* @returns {number}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ export default () => ({
|
|||
startVersion: null, // Null unless a target diff is selected for comparison that is not the "base" diff
|
||||
diffFiles: [],
|
||||
coverageFiles: {},
|
||||
codequalityDiff: {},
|
||||
mergeRequestDiffs: [],
|
||||
mergeRequestDiff: null,
|
||||
diffViewType: viewTypeFromQueryString || viewTypeFromCookie || defaultViewType,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import * as actions from '../actions';
|
||||
import * as actions from 'ee_else_ce/diffs/store/actions';
|
||||
import createState from 'ee_else_ce/diffs/store/modules/diff_state';
|
||||
import mutations from 'ee_else_ce/diffs/store/mutations';
|
||||
import * as getters from '../getters';
|
||||
import mutations from '../mutations';
|
||||
import createState from './diff_state';
|
||||
|
||||
export default () => ({
|
||||
namespaced: true,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ export const SET_MR_FILE_REVIEWS = 'SET_MR_FILE_REVIEWS';
|
|||
|
||||
export const SET_DIFF_VIEW_TYPE = 'SET_DIFF_VIEW_TYPE';
|
||||
export const SET_COVERAGE_DATA = 'SET_COVERAGE_DATA';
|
||||
export const SET_CODEQUALITY_DATA = 'SET_CODEQUALITY_DATA';
|
||||
export const SET_MERGE_REQUEST_DIFFS = 'SET_MERGE_REQUEST_DIFFS';
|
||||
export const TOGGLE_LINE_HAS_FORM = 'TOGGLE_LINE_HAS_FORM';
|
||||
export const ADD_CONTEXT_LINES = 'ADD_CONTEXT_LINES';
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ export default {
|
|||
endpointMetadata,
|
||||
endpointBatch,
|
||||
endpointCoverage,
|
||||
endpointCodequality,
|
||||
endpointUpdateUser,
|
||||
projectPath,
|
||||
dismissEndpoint,
|
||||
|
|
@ -47,7 +46,6 @@ export default {
|
|||
endpointMetadata,
|
||||
endpointBatch,
|
||||
endpointCoverage,
|
||||
endpointCodequality,
|
||||
endpointUpdateUser,
|
||||
projectPath,
|
||||
dismissEndpoint,
|
||||
|
|
@ -91,10 +89,6 @@ export default {
|
|||
Object.assign(state, { coverageFiles });
|
||||
},
|
||||
|
||||
[types.SET_CODEQUALITY_DATA](state, codequalityDiffData) {
|
||||
Object.assign(state, { codequalityDiff: codequalityDiffData });
|
||||
},
|
||||
|
||||
[types.RENDER_FILE](state, file) {
|
||||
renderFile(file);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import { GlButton, GlCard, GlSprintf } from '@gitlab/ui';
|
||||
import ExperimentTracking from '~/experimentation/experiment_tracking';
|
||||
import { mergeUrlParams } from '~/lib/utils/url_utility';
|
||||
import { s__, sprintf } from '~/locale';
|
||||
import { HELLO_WORLD_TEMPLATE_KEY } from '../../constants';
|
||||
|
|
@ -10,6 +11,7 @@ export default {
|
|||
GlCard,
|
||||
GlSprintf,
|
||||
},
|
||||
HELLO_WORLD_TEMPLATE_KEY,
|
||||
i18n: {
|
||||
cta: s__('Pipelines|Use template'),
|
||||
testTemplates: {
|
||||
|
|
@ -51,6 +53,14 @@ export default {
|
|||
),
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
trackEvent(template) {
|
||||
const tracking = new ExperimentTracking('pipeline_empty_state_templates', {
|
||||
label: template,
|
||||
});
|
||||
tracking.event('template_clicked');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
|
|
@ -82,6 +92,7 @@ export default {
|
|||
variant="confirm"
|
||||
:href="helloWorldTemplateUrl"
|
||||
data-testid="test-template-link"
|
||||
@click="trackEvent($options.HELLO_WORLD_TEMPLATE_KEY)"
|
||||
>
|
||||
{{ $options.i18n.cta }}
|
||||
</gl-button>
|
||||
|
|
@ -121,6 +132,7 @@ export default {
|
|||
variant="confirm"
|
||||
:href="template.link"
|
||||
data-testid="template-link"
|
||||
@click="trackEvent(template.name)"
|
||||
>
|
||||
{{ $options.i18n.cta }}
|
||||
</gl-button>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module MergeRequests
|
||||
class ResolveTodosService
|
||||
include BaseServiceUtility
|
||||
|
||||
def initialize(merge_request, user)
|
||||
@merge_request = merge_request
|
||||
@user = user
|
||||
end
|
||||
|
||||
def async_execute
|
||||
if Feature.enabled?(:resolve_merge_request_todos_async, merge_request.target_project, default_enabled: :yaml)
|
||||
MergeRequests::ResolveTodosWorker.perform_async(merge_request.id, user.id)
|
||||
else
|
||||
execute
|
||||
end
|
||||
end
|
||||
|
||||
def execute
|
||||
todo_service.resolve_todos_for_target(merge_request, user)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :merge_request, :user
|
||||
end
|
||||
end
|
||||
|
|
@ -147,7 +147,11 @@ module MergeRequests
|
|||
def resolve_todos(merge_request, old_labels, old_assignees, old_reviewers)
|
||||
return unless has_changes?(merge_request, old_labels: old_labels, old_assignees: old_assignees, old_reviewers: old_reviewers)
|
||||
|
||||
todo_service.resolve_todos_for_target(merge_request, current_user)
|
||||
service_user = current_user
|
||||
|
||||
merge_request.run_after_commit_or_now do
|
||||
::MergeRequests::ResolveTodosService.new(merge_request, service_user).async_execute
|
||||
end
|
||||
end
|
||||
|
||||
def handle_target_branch_change(merge_request)
|
||||
|
|
|
|||
|
|
@ -20,20 +20,20 @@
|
|||
|
||||
.float-right
|
||||
- if impersonation_enabled? && @user != current_user && @user.can?(:log_in)
|
||||
= link_to 'Impersonate', impersonate_admin_user_path(@user), method: :post, class: "btn btn-info gl-button btn-grouped", data: { qa_selector: 'impersonate_user_link' }
|
||||
= link_to _('Impersonate'), impersonate_admin_user_path(@user), method: :post, class: "btn btn-info gl-button btn-grouped", data: { qa_selector: 'impersonate_user_link' }
|
||||
= link_to edit_admin_user_path(@user), class: "btn btn-default gl-button btn-grouped" do
|
||||
= sprite_icon('pencil-square', css_class: 'gl-icon gl-button-icon')
|
||||
= _('Edit')
|
||||
%hr
|
||||
%ul.nav-links.nav.nav-tabs
|
||||
= nav_link(path: 'users#show') do
|
||||
= link_to "Account", admin_user_path(@user)
|
||||
= link_to _("Account"), admin_user_path(@user)
|
||||
= nav_link(path: 'users#projects') do
|
||||
= link_to "Groups and projects", projects_admin_user_path(@user)
|
||||
= link_to _("Groups and projects"), projects_admin_user_path(@user)
|
||||
= nav_link(path: 'users#keys') do
|
||||
= link_to "SSH keys", keys_admin_user_path(@user)
|
||||
= link_to _("SSH keys"), keys_admin_user_path(@user)
|
||||
= nav_link(controller: :identities) do
|
||||
= link_to "Identities", admin_user_identities_path(@user)
|
||||
= link_to _("Identities"), admin_user_identities_path(@user)
|
||||
= nav_link(controller: :impersonation_tokens) do
|
||||
= link_to "Impersonation Tokens", admin_user_impersonation_tokens_path(@user)
|
||||
= link_to _("Impersonation Tokens"), admin_user_impersonation_tokens_path(@user)
|
||||
.gl-mb-3
|
||||
|
|
|
|||
|
|
@ -3,16 +3,16 @@
|
|||
.table-mobile-header{ role: 'rowheader' }= _('Type')
|
||||
.table-mobile-content
|
||||
- if runner.group_type?
|
||||
%span.badge.badge-success
|
||||
%span.badge.badge-pill.gl-badge.sm.badge-success
|
||||
= _('group')
|
||||
- else
|
||||
%span.badge.badge-info
|
||||
%span.badge.badge-pill.gl-badge.sm.badge-info
|
||||
= _('specific')
|
||||
- if runner.locked?
|
||||
%span.badge.badge-warning
|
||||
%span.badge.badge-pill.gl-badge.sm.badge-warning
|
||||
= _('locked')
|
||||
- unless runner.active?
|
||||
%span.badge.badge-danger
|
||||
%span.badge.badge-pill.gl-badge.sm.badge-danger
|
||||
= _('paused')
|
||||
|
||||
.table-section.section-10
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
.float-right
|
||||
%span.key-created-at
|
||||
= s_('Profiles|Created %{time_ago}'.html_safe) % { time_ago: time_ago_with_tooltip(key.created_at) }
|
||||
= link_to profile_gpg_key_path(key), data: { confirm: _('Are you sure? Removing this GPG key does not affect already signed commits.') }, method: :delete, class: "gl-button btn btn-danger gl-ml-3" do
|
||||
= link_to profile_gpg_key_path(key), data: { confirm: _('Are you sure? Removing this GPG key does not affect already signed commits.') }, method: :delete, class: "gl-button btn btn-icon btn-danger gl-ml-3" do
|
||||
%span.sr-only= _('Remove')
|
||||
= sprite_icon('remove')
|
||||
= link_to revoke_profile_gpg_key_path(key), data: { confirm: _('Are you sure? All commits that were signed with this GPG key will be unverified.') }, method: :put, class: "gl-button btn btn-danger gl-ml-3" do
|
||||
|
|
|
|||
|
|
@ -1908,6 +1908,14 @@
|
|||
:weight: 1
|
||||
:idempotent: true
|
||||
:tags: []
|
||||
- :name: merge_requests_resolve_todos
|
||||
:feature_category: :code_review
|
||||
:has_external_dependencies:
|
||||
:urgency: :high
|
||||
:resource_boundary: :unknown
|
||||
:weight: 1
|
||||
:idempotent: true
|
||||
:tags: []
|
||||
- :name: metrics_dashboard_prune_old_annotations
|
||||
:feature_category: :metrics
|
||||
:has_external_dependencies:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class MergeRequests::ResolveTodosWorker
|
||||
include ApplicationWorker
|
||||
|
||||
feature_category :code_review
|
||||
urgency :high
|
||||
deduplicate :until_executed
|
||||
idempotent!
|
||||
|
||||
def perform(merge_request_id, user_id)
|
||||
merge_request = MergeRequest.find(merge_request_id)
|
||||
user = User.find(user_id)
|
||||
|
||||
MergeRequests::ResolveTodosService.new(merge_request, user).execute
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Resolve merge request todos asynchronously on update
|
||||
merge_request: 58647
|
||||
author:
|
||||
type: performance
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Externalise strings in admin/users/_head.html.haml
|
||||
merge_request: 58101
|
||||
author: nuwe1
|
||||
type: other
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add user index on spam logs
|
||||
merge_request: 59151
|
||||
author:
|
||||
type: performance
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add btn-icon class for GPG key delete button
|
||||
merge_request: 57974
|
||||
author: Yogi (@yo)
|
||||
type: changed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Update metric definition under verify testing group
|
||||
merge_request: 59028
|
||||
author:
|
||||
type: other
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: resolve_merge_request_todos_async
|
||||
introduced_by_url:
|
||||
rollout_issue_url:
|
||||
milestone: '13.11'
|
||||
type: development
|
||||
group: group::code review
|
||||
default_enabled: false
|
||||
|
|
@ -17,4 +17,3 @@ tier:
|
|||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
skip_validation: true
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
---
|
||||
key_path: redis_hll_counters.testing.i_testing_metrics_report_artifact_uploaders_monthly
|
||||
description: Internal Tracking to count number of unit tests parsed for planning of
|
||||
future code testing features. Data available [here](https://app.periscopedata.com/app/gitlab/788674/Verify:Testing-Group-Metrics?widget=10454394&udv=0)
|
||||
product_section: ops
|
||||
product_stage: verify
|
||||
product_group: group::testing
|
||||
product_category: code_testing
|
||||
value_type: number
|
||||
status: data_available
|
||||
time_frame: 28d
|
||||
data_source: redis_hll
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
skip_validation: true
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
---
|
||||
key_path: counts_monthly.aggregated_metrics.i_testing_paid_monthly_active_user_total
|
||||
description: ''
|
||||
product_section: ''
|
||||
product_stage: ''
|
||||
product_group: ''
|
||||
product_category: ''
|
||||
value_type: number
|
||||
status: data_available
|
||||
time_frame: 28d
|
||||
data_source: database
|
||||
distribution:
|
||||
- ce
|
||||
tier:
|
||||
- free
|
||||
skip_validation: true
|
||||
|
|
@ -6,11 +6,10 @@ product_stage: ''
|
|||
product_group: ''
|
||||
product_category: ''
|
||||
value_type: number
|
||||
status: data_available
|
||||
status: removed
|
||||
time_frame: 28d
|
||||
data_source: redis_hll
|
||||
distribution:
|
||||
- ce
|
||||
tier:
|
||||
- free
|
||||
skip_validation: true
|
||||
|
|
|
|||
|
|
@ -17,4 +17,3 @@ tier:
|
|||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
skip_validation: true
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
---
|
||||
key_path: redis_hll_counters.testing.i_testing_metrics_report_artifact_uploaders_weekly
|
||||
description: Internal Tracking to count number of unit tests parsed for planning of
|
||||
future code testing features. Data available [here](https://app.periscopedata.com/app/gitlab/788674/Verify:Testing-Group-Metrics?widget=10454394&udv=0)
|
||||
product_section: ops
|
||||
product_stage: verify
|
||||
product_group: group::testing
|
||||
product_category: code_testing
|
||||
value_type: number
|
||||
status: data_available
|
||||
time_frame: 7d
|
||||
data_source: redis_hll
|
||||
distribution:
|
||||
- ee
|
||||
- ce
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
skip_validation: true
|
||||
|
|
@ -218,6 +218,8 @@
|
|||
- 1
|
||||
- - merge_requests_handle_assignees_change
|
||||
- 1
|
||||
- - merge_requests_resolve_todos
|
||||
- 1
|
||||
- - metrics_dashboard_prune_old_annotations
|
||||
- 1
|
||||
- - metrics_dashboard_sync_dashboards
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddUserIndexOnSpamLogs < ActiveRecord::Migration[6.0]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
INDEX_NAME = 'index_spam_logs_on_user_id'
|
||||
|
||||
def up
|
||||
add_concurrent_index :spam_logs, :user_id, name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index_by_name :spam_logs, INDEX_NAME
|
||||
end
|
||||
end
|
||||
|
|
@ -6,13 +6,13 @@ class BackfillEventsIdForBigintConversion < ActiveRecord::Migration[6.0]
|
|||
DOWNTIME = false
|
||||
|
||||
def up
|
||||
return unless Gitlab.dev_env_or_com?
|
||||
return unless should_run?
|
||||
|
||||
backfill_conversion_of_integer_to_bigint :events, :id, batch_size: 15000, sub_batch_size: 100
|
||||
end
|
||||
|
||||
def down
|
||||
return unless Gitlab.dev_env_or_com?
|
||||
return unless should_run?
|
||||
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.where(job_class_name: 'CopyColumnUsingBackgroundMigrationJob')
|
||||
|
|
@ -20,4 +20,10 @@ class BackfillEventsIdForBigintConversion < ActiveRecord::Migration[6.0]
|
|||
.where('job_arguments = ?', %w[id id_convert_to_bigint].to_json)
|
||||
.delete_all
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def should_run?
|
||||
Gitlab.dev_or_test_env? || Gitlab.com?
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@ class BackfillPushEventPayloadEventIdForBigintConversion < ActiveRecord::Migrati
|
|||
DOWNTIME = false
|
||||
|
||||
def up
|
||||
return unless Gitlab.dev_env_or_com?
|
||||
return unless should_run?
|
||||
|
||||
backfill_conversion_of_integer_to_bigint :push_event_payloads, :event_id, primary_key: :event_id,
|
||||
batch_size: 15000, sub_batch_size: 100
|
||||
end
|
||||
|
||||
def down
|
||||
return unless Gitlab.dev_env_or_com?
|
||||
return unless should_run?
|
||||
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.where(job_class_name: 'CopyColumnUsingBackgroundMigrationJob')
|
||||
|
|
@ -21,4 +21,10 @@ class BackfillPushEventPayloadEventIdForBigintConversion < ActiveRecord::Migrati
|
|||
.where('job_arguments = ?', %w[event_id event_id_convert_to_bigint].to_json)
|
||||
.delete_all
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def should_run?
|
||||
Gitlab.dev_or_test_env? || Gitlab.com?
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
4a1435a56b8e5cddd83b844f84374bca91810bbfc5f44faf2a53fd41f93be69c
|
||||
|
|
@ -23942,6 +23942,8 @@ CREATE UNIQUE INDEX index_sop_configs_on_project_id ON security_orchestration_po
|
|||
|
||||
CREATE INDEX index_sop_configurations_project_id_policy_project_id ON security_orchestration_policy_configurations USING btree (security_policy_management_project_id, project_id);
|
||||
|
||||
CREATE INDEX index_spam_logs_on_user_id ON spam_logs USING btree (user_id);
|
||||
|
||||
CREATE INDEX index_sprints_iterations_cadence_id ON sprints USING btree (iterations_cadence_id);
|
||||
|
||||
CREATE INDEX index_sprints_on_description_trigram ON sprints USING gin (description gin_trgm_ops);
|
||||
|
|
|
|||
|
|
@ -281,7 +281,6 @@ WARNING:
|
|||
This list of limitations only reflects the latest version of GitLab. If you are using an older version, extra limitations may be in place.
|
||||
|
||||
- Pushing directly to a **secondary** node redirects (for HTTP) or proxies (for SSH) the request to the **primary** node instead of [handling it directly](https://gitlab.com/gitlab-org/gitlab/-/issues/1381), except when using Git over HTTP with credentials embedded within the URI. For example, `https://user:password@secondary.tld`.
|
||||
- Cloning, pulling, or pushing repositories that exist on the **primary** node but not on the **secondary** nodes where [selective synchronization](replication/configuration.md#selective-synchronization) does not include the project is not supported over SSH [but support is planned](https://gitlab.com/groups/gitlab-org/-/epics/2562). HTTP(S) is supported.
|
||||
- The **primary** node has to be online for OAuth login to happen. Existing sessions and Git are not affected. Support for the **secondary** node to use an OAuth provider independent from the primary is [being planned](https://gitlab.com/gitlab-org/gitlab/-/issues/208465).
|
||||
- The installation takes multiple manual steps that together can take about an hour depending on circumstances. We are working on improving this experience. See [Omnibus GitLab issue #2978](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/2978) for details.
|
||||
- Real-time updates of issues/merge requests (for example, via long polling) doesn't work on the **secondary** node.
|
||||
|
|
@ -289,6 +288,7 @@ This list of limitations only reflects the latest version of GitLab. If you are
|
|||
- Object pools for forked project deduplication work only on the **primary** node, and are duplicated on the **secondary** node.
|
||||
- GitLab Runners cannot register with a **secondary** node. Support for this is [planned for the future](https://gitlab.com/gitlab-org/gitlab/-/issues/3294).
|
||||
- Geo **secondary** nodes can not be configured to [use high-availability configurations of PostgreSQL](https://gitlab.com/groups/gitlab-org/-/epics/2536).
|
||||
- [Selective synchronization](replication/configuration.md#selective-synchronization) only limits what repositories are replicated. The entire PostgreSQL data is still replicated. Selective synchronization is not built to accomodate compliance / export control use cases.
|
||||
|
||||
### Limitations on replication/verification
|
||||
|
||||
|
|
|
|||
|
|
@ -332,12 +332,13 @@ can see it.
|
|||
|
||||
## Run the spec
|
||||
|
||||
Before running the spec, confirm:
|
||||
Before running the spec, make sure that:
|
||||
|
||||
- The GDK is installed.
|
||||
- The GDK is running on port 3000 locally.
|
||||
- GDK is installed.
|
||||
- GDK is running locally on port 3000.
|
||||
- No additional [RSpec metadata tags](rspec_metadata_tests.md) have been applied.
|
||||
- Your working directory is `qa/` within your GDK GitLab installation.
|
||||
- Your GitLab instance-level settings are default. If you changed the default settings, some tests might have unexpected results.
|
||||
|
||||
To run the spec, run the following command:
|
||||
|
||||
|
|
|
|||
|
|
@ -6106,15 +6106,15 @@ Tiers: `free`
|
|||
|
||||
### `counts_monthly.aggregated_metrics.i_testing_paid_monthly_active_user_total`
|
||||
|
||||
Missing description
|
||||
Aggregated count of users who have engaged with a Premium or Ultimate tier testing feature per month.
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183209_i_testing_paid_monthly_active_user_total.yml)
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216183209_i_testing_paid_monthly_active_user_total.yml)
|
||||
|
||||
Group: ``
|
||||
Group: `group::testing`
|
||||
|
||||
Status: `data_available`
|
||||
|
||||
Tiers: `free`
|
||||
Tiers: `premium`, `ultimate`
|
||||
|
||||
### `counts_monthly.aggregated_metrics.incident_management_alerts_total_unique_counts`
|
||||
|
||||
|
|
@ -6274,15 +6274,15 @@ Tiers:
|
|||
|
||||
### `counts_weekly.aggregated_metrics.i_testing_paid_monthly_active_user_total`
|
||||
|
||||
Missing description
|
||||
Aggregated count of users who have engaged with a Premium or Ultimate tier testing feature per week.
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216183219_i_testing_paid_monthly_active_user_total.yml)
|
||||
|
||||
Group: ``
|
||||
Group: `group::testing`
|
||||
|
||||
Status: `data_available`
|
||||
|
||||
Tiers:
|
||||
Tiers: `premium`, `ultimate`
|
||||
|
||||
### `counts_weekly.aggregated_metrics.incident_management_alerts_total_unique_counts`
|
||||
|
||||
|
|
@ -13654,7 +13654,7 @@ Tiers: `premium`, `ultimate`
|
|||
|
||||
### `redis_hll_counters.testing.i_testing_full_code_quality_report_total_weekly`
|
||||
|
||||
Count of unique users per week|month who visit the full code quality report
|
||||
Count of unique users per week who visit the full code quality report
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216182145_i_testing_full_code_quality_report_total_weekly.yml)
|
||||
|
||||
|
|
@ -13666,7 +13666,7 @@ Tiers: `premium`, `ultimate`
|
|||
|
||||
### `redis_hll_counters.testing.i_testing_group_code_coverage_project_click_total_monthly`
|
||||
|
||||
Count of unique users per week|month who click on a project link in the group code coverage table
|
||||
Aggregated count of unique users who have clicked from group code coverage page to an individual project page each month.
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182153_i_testing_group_code_coverage_project_click_total_monthly.yml)
|
||||
|
||||
|
|
@ -13678,19 +13678,19 @@ Tiers: `premium`, `ultimate`
|
|||
|
||||
### `redis_hll_counters.testing.i_testing_group_code_coverage_project_click_total_weekly`
|
||||
|
||||
Missing description
|
||||
Aggregated count of unique users who have clicked from group code coverage page to an individual project page each week.
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184132_i_testing_group_code_coverage_project_click_total_weekly.yml)
|
||||
|
||||
Group: ``
|
||||
Group: `group::testing`
|
||||
|
||||
Status: `data_available`
|
||||
|
||||
Tiers:
|
||||
Tiers: `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.testing.i_testing_group_code_coverage_visit_total_monthly`
|
||||
|
||||
Count of unique users per week|month who visited the group code coverage page
|
||||
Count of unique users per month who visited the group code coverage page
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182143_i_testing_group_code_coverage_visit_total_monthly.yml)
|
||||
|
||||
|
|
@ -13702,7 +13702,7 @@ Tiers: `premium`, `ultimate`
|
|||
|
||||
### `redis_hll_counters.testing.i_testing_group_code_coverage_visit_total_weekly`
|
||||
|
||||
Count of unique users per week|month who visited the group code coverage page
|
||||
Count of unique users per week who visited the group code coverage page
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216182141_i_testing_group_code_coverage_visit_total_weekly.yml)
|
||||
|
||||
|
|
@ -13714,7 +13714,7 @@ Tiers: `premium`, `ultimate`
|
|||
|
||||
### `redis_hll_counters.testing.i_testing_load_performance_widget_total_monthly`
|
||||
|
||||
Count of unique users per week|month who expanded the load performance report MR widget
|
||||
Count of unique users per month who expanded the load performance report MR widget
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182156_i_testing_load_performance_widget_total_monthly.yml)
|
||||
|
||||
|
|
@ -13726,7 +13726,7 @@ Tiers: `premium`, `ultimate`
|
|||
|
||||
### `redis_hll_counters.testing.i_testing_load_performance_widget_total_weekly`
|
||||
|
||||
Count of unique users per week|month who expanded the load performance report MR widget
|
||||
Count of unique users per week who expanded the load performance report MR widget
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216182154_i_testing_load_performance_widget_total_weekly.yml)
|
||||
|
||||
|
|
@ -13738,31 +13738,31 @@ Tiers: `premium`, `ultimate`
|
|||
|
||||
### `redis_hll_counters.testing.i_testing_metrics_report_artifact_uploaders_monthly`
|
||||
|
||||
Internal Tracking to count number of unit tests parsed for planning of future code testing features. Data available [here](https://app.periscopedata.com/app/gitlab/788674/Verify:Testing-Group-Metrics?widget=10454394&udv=0)
|
||||
Tracks number of metrics reports uploaded monthly.
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182200_i_testing_metrics_report_artifact_uploaders_monthly.yml)
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182200_i_testing_metrics_report_artifact_uploaders_monthly.yml)
|
||||
|
||||
Group: `group::testing`
|
||||
|
||||
Status: `data_available`
|
||||
|
||||
Tiers: `free`, `premium`, `ultimate`
|
||||
Tiers: `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.testing.i_testing_metrics_report_artifact_uploaders_weekly`
|
||||
|
||||
Internal Tracking to count number of unit tests parsed for planning of future code testing features. Data available [here](https://app.periscopedata.com/app/gitlab/788674/Verify:Testing-Group-Metrics?widget=10454394&udv=0)
|
||||
Count of unique users per week who trigger a pipeline that uploads a metrics report.
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216182158_i_testing_metrics_report_artifact_uploaders_weekly.yml)
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216182158_i_testing_metrics_report_artifact_uploaders_weekly.yml)
|
||||
|
||||
Group: `group::testing`
|
||||
|
||||
Status: `data_available`
|
||||
|
||||
Tiers: `free`, `premium`, `ultimate`
|
||||
Tiers: `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.testing.i_testing_metrics_report_widget_total_monthly`
|
||||
|
||||
Count of unique users per week|month who expanded the metrics report MR widget
|
||||
Count of unique users per month who expanded the metrics report MR widget
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182139_i_testing_metrics_report_widget_total_monthly.yml)
|
||||
|
||||
|
|
@ -13774,7 +13774,7 @@ Tiers: `premium`, `ultimate`
|
|||
|
||||
### `redis_hll_counters.testing.i_testing_metrics_report_widget_total_weekly`
|
||||
|
||||
Count of unique users per week|month who expanded the metrics report MR widget
|
||||
Count of unique users per week who expanded the metrics report MR widget
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216182138_i_testing_metrics_report_widget_total_weekly.yml)
|
||||
|
||||
|
|
@ -13810,7 +13810,7 @@ Tiers: `free`, `premium`, `ultimate`
|
|||
|
||||
### `redis_hll_counters.testing.i_testing_web_performance_widget_total_monthly`
|
||||
|
||||
Count of unique users per week|month who expanded the browser performance report MR widget
|
||||
Count of unique users per month who expanded the browser performance report MR widget
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182151_i_testing_web_performance_widget_total_monthly.yml)
|
||||
|
||||
|
|
@ -13822,7 +13822,7 @@ Tiers: `premium`, `ultimate`
|
|||
|
||||
### `redis_hll_counters.testing.i_testing_web_performance_widget_total_weekly`
|
||||
|
||||
Count of unique users per week|month who expanded the browser performance report MR widget
|
||||
Count of unique users per week who expanded the browser performance report MR widget
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216182149_i_testing_web_performance_widget_total_weekly.yml)
|
||||
|
||||
|
|
@ -13840,7 +13840,7 @@ Missing description
|
|||
|
||||
Group: ``
|
||||
|
||||
Status: `data_available`
|
||||
Status: `removed`
|
||||
|
||||
Tiers: `free`
|
||||
|
||||
|
|
@ -13852,9 +13852,9 @@ Missing description
|
|||
|
||||
Group: ``
|
||||
|
||||
Status: `data_available`
|
||||
Status: `removed`
|
||||
|
||||
Tiers:
|
||||
Tiers: `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.user_packages.i_package_composer_user_monthly`
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ The following table describes the version types and their release cadence:
|
|||
|
||||
| Version type | Description | Cadence |
|
||||
|:-------------|:------------|:--------|
|
||||
| Major | For significant changes, or when any backward-incompatible changes are introduced to the public API. | Yearly. The next major release is GitLab 14.0 on May 22, 2021. Subsequent major releases will be scheduled for May 22 each year, by default. |
|
||||
| Major | For significant changes, or when any backward-incompatible changes are introduced to the public API. | Yearly. The next major release is GitLab 14.0 on June 22, 2021 (one month later than typical, details in [this issue](https://gitlab.com/gitlab-com/Product/-/issues/2337)). Subsequent major releases will be scheduled for May 22 each year, by default. |
|
||||
| Minor | For when new backward-compatible functionality is introduced to the public API, a minor feature is introduced, or when a set of smaller features is rolled out. | Monthly on the 22nd. |
|
||||
| Patch | For backward-compatible bug fixes that fix incorrect behavior. See [Patch releases](#patch-releases). | As needed. |
|
||||
|
||||
|
|
|
|||
|
|
@ -323,14 +323,6 @@ in a comment or description field.
|
|||
Assignees in the sidebar are updated in real time. This feature is **disabled by default**.
|
||||
To enable it, you need to enable [ActionCable in-app mode](https://docs.gitlab.com/omnibus/settings/actioncable.html).
|
||||
|
||||
## Cached issue count **(FREE SELF)**
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/243753) in GitLab 13.9.
|
||||
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/323493) in GitLab 13.11.
|
||||
|
||||
In a group, the sidebar displays the total count of open issues and this value is cached if higher
|
||||
than 1000. The cached value is rounded to thousands (or millions) and updated every 24 hours.
|
||||
|
||||
## Similar issues
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22866) in GitLab 11.6.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ group: Release
|
|||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
# Create a Pages website from a new project template
|
||||
# Create a Pages website from a template
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47857) in GitLab 11.8.
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ To create a GitLab Pages website:
|
|||
| [Create a `gitlab-ci.yml` file from scratch](getting_started/pages_from_scratch.md) | Add a Pages site to an existing project. Learn how to create and configure your own CI file. |
|
||||
| [Use a `.gitlab-ci.yml` template](getting_started/pages_ci_cd_template.md) | Add a Pages site to an existing project. Use a pre-populated CI template file. |
|
||||
| [Fork a sample project](getting_started/pages_forked_sample_project.md) | Create a new project with Pages already configured by forking a sample project. |
|
||||
| [Use a new project template](getting_started/pages_new_project_template.md) | Create a new project with Pages already configured by using a new project template. |
|
||||
| [Use a project template](getting_started/pages_new_project_template.md) | Create a new project with Pages already configured by using a template. |
|
||||
|
||||
To update a GitLab Pages website:
|
||||
|
||||
|
|
|
|||
|
|
@ -142,14 +142,10 @@ module Gitlab
|
|||
end
|
||||
|
||||
def job_variables
|
||||
return unless ::Feature.enabled?(:ci_workflow_rules_variables, default_enabled: :yaml)
|
||||
|
||||
variables_value.to_h
|
||||
end
|
||||
|
||||
def root_variables_inheritance
|
||||
return unless ::Feature.enabled?(:ci_workflow_rules_variables, default_enabled: :yaml)
|
||||
|
||||
inherit_entry&.variables_entry&.value
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ module Gitlab
|
|||
name: name,
|
||||
instance: instance,
|
||||
variables: variables, # https://gitlab.com/gitlab-org/gitlab/-/issues/300581
|
||||
job_variables: job_variables,
|
||||
job_variables: variables,
|
||||
parallel: { total: total }
|
||||
}.compact
|
||||
end
|
||||
|
|
@ -61,12 +61,6 @@ module Gitlab
|
|||
private
|
||||
|
||||
attr_reader :job_name, :instance, :variables, :total
|
||||
|
||||
def job_variables
|
||||
return unless ::Feature.enabled?(:ci_workflow_rules_variables, default_enabled: :yaml)
|
||||
|
||||
variables
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ module Gitlab
|
|||
def perform!
|
||||
raise ArgumentError, 'missing YAML processor result' unless @command.yaml_processor_result
|
||||
|
||||
if ::Feature.enabled?(:ci_workflow_rules_variables, default_enabled: :yaml)
|
||||
if ::Feature.enabled?(:ci_workflow_rules_variables, pipeline.project, default_enabled: :yaml)
|
||||
raise ArgumentError, 'missing workflow rules result' unless @command.workflow_rules_result
|
||||
end
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def root_variables
|
||||
if ::Feature.enabled?(:ci_workflow_rules_variables, default_enabled: :yaml)
|
||||
if ::Feature.enabled?(:ci_workflow_rules_variables, pipeline.project, default_enabled: :yaml)
|
||||
::Gitlab::Ci::Variables::Helpers.merge_variables(
|
||||
@command.yaml_processor_result.root_variables, @command.workflow_rules_result.variables
|
||||
)
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def recalculate_yaml_variables!
|
||||
return unless ::Feature.enabled?(:ci_workflow_rules_variables, default_enabled: :yaml)
|
||||
return unless ::Feature.enabled?(:ci_workflow_rules_variables, @pipeline.project, default_enabled: :yaml)
|
||||
|
||||
@seed_attributes[:yaml_variables] = Gitlab::Ci::Variables::Helpers.inherit_yaml_variables(
|
||||
from: @context.root_variables, to: @job_variables, inheritance: @root_variables_inheritance
|
||||
|
|
|
|||
|
|
@ -190,11 +190,7 @@ module Gitlab
|
|||
migration_status = batch_max_value.nil? ? :finished : :active
|
||||
batch_max_value ||= batch_min_value
|
||||
|
||||
# We keep track of the estimated number of tuples to reason later
|
||||
# about the overall progress of a migration.
|
||||
total_tuple_count = Gitlab::Database::PgClass.for_table(batch_table_name)&.cardinality_estimate
|
||||
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration.create!(
|
||||
migration = Gitlab::Database::BackgroundMigration::BatchedMigration.create!(
|
||||
job_class_name: job_class_name,
|
||||
table_name: batch_table_name,
|
||||
column_name: batch_column_name,
|
||||
|
|
@ -205,8 +201,18 @@ module Gitlab
|
|||
batch_size: batch_size,
|
||||
sub_batch_size: sub_batch_size,
|
||||
job_arguments: job_arguments,
|
||||
status: migration_status,
|
||||
total_tuple_count: total_tuple_count)
|
||||
status: migration_status)
|
||||
|
||||
# This guard is necessary since #total_tuple_count was only introduced schema-wise,
|
||||
# after this migration helper had been used for the first time.
|
||||
return migration unless migration.respond_to?(:total_tuple_count)
|
||||
|
||||
# We keep track of the estimated number of tuples to reason later
|
||||
# about the overall progress of a migration.
|
||||
migration.total_tuple_count = Gitlab::Database::PgClass.for_table(batch_table_name)&.cardinality_estimate
|
||||
migration.save!
|
||||
|
||||
migration
|
||||
end
|
||||
|
||||
def perform_background_migration_inline?
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ module Gitlab
|
|||
{
|
||||
tag_list: tags || [],
|
||||
yaml_variables: yaml_variables, # https://gitlab.com/gitlab-org/gitlab/-/issues/300581
|
||||
job_variables: job_variables,
|
||||
job_variables: yaml_variables,
|
||||
options: {
|
||||
image: image_value,
|
||||
services: services_value,
|
||||
|
|
@ -74,12 +74,6 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
def job_variables
|
||||
return unless ::Feature.enabled?(:ci_workflow_rules_variables, default_enabled: :yaml)
|
||||
|
||||
yaml_variables
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -16044,6 +16044,9 @@ msgstr ""
|
|||
msgid "ImageViewerDimensions|W"
|
||||
msgstr ""
|
||||
|
||||
msgid "Impersonate"
|
||||
msgstr ""
|
||||
|
||||
msgid "Impersonation Tokens"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -27173,6 +27176,9 @@ msgstr ""
|
|||
msgid "SSH key"
|
||||
msgstr ""
|
||||
|
||||
msgid "SSH keys"
|
||||
msgstr ""
|
||||
|
||||
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -27669,7 +27675,7 @@ msgstr ""
|
|||
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
|
||||
msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to specify security policies that are important to you and enforce them with every commit."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Create a policy"
|
||||
|
|
@ -29017,6 +29023,9 @@ msgstr ""
|
|||
msgid "Something went wrong on our end"
|
||||
msgstr ""
|
||||
|
||||
msgid "Something went wrong on our end while loading the code quality diff."
|
||||
msgstr ""
|
||||
|
||||
msgid "Something went wrong on our end."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -30988,7 +30997,7 @@ msgstr ""
|
|||
msgid "The merge request can now be merged."
|
||||
msgstr ""
|
||||
|
||||
msgid "The merge request has been updated, and the number of code quality violations in this file has changed."
|
||||
msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
|
||||
msgstr ""
|
||||
|
||||
msgid "The metric must be one of %{metrics}."
|
||||
|
|
|
|||
|
|
@ -176,11 +176,11 @@
|
|||
"commander": "^2.18.0",
|
||||
"custom-jquery-matchers": "^2.1.0",
|
||||
"docdash": "^1.0.2",
|
||||
"eslint": "7.21.0",
|
||||
"eslint": "7.24.0",
|
||||
"eslint-import-resolver-jest": "3.0.0",
|
||||
"eslint-import-resolver-webpack": "0.13.0",
|
||||
"eslint-plugin-jasmine": "4.1.2",
|
||||
"eslint-plugin-no-jquery": "2.5.0",
|
||||
"eslint-plugin-no-jquery": "2.6.0",
|
||||
"gettext-extractor": "^3.5.3",
|
||||
"gettext-extractor-vue": "^5.0.0",
|
||||
"glob": "^7.1.6",
|
||||
|
|
|
|||
|
|
@ -225,6 +225,10 @@ module QA
|
|||
)
|
||||
end
|
||||
|
||||
def health_check_failure_message?(msg)
|
||||
['error when pinging healthcheck', 'failed checking node health'].include?(msg)
|
||||
end
|
||||
|
||||
def wait_for_no_praefect_storage_error
|
||||
# If a healthcheck error was the last message to be logged, we'll keep seeing that message even if it's no longer a problem
|
||||
# That is, there's no message shown in the Praefect logs when the healthcheck succeeds
|
||||
|
|
@ -241,7 +245,7 @@ module QA
|
|||
QA::Runtime::Logger.debug(line.chomp)
|
||||
log = JSON.parse(line)
|
||||
|
||||
break true if log['msg'] != 'error when pinging healthcheck'
|
||||
break true unless health_check_failure_message?(log['msg'])
|
||||
rescue JSON::ParserError
|
||||
# Ignore lines that can't be parsed as JSON
|
||||
end
|
||||
|
|
@ -302,7 +306,7 @@ module QA
|
|||
QA::Runtime::Logger.debug(line.chomp)
|
||||
log = JSON.parse(line)
|
||||
|
||||
log['msg'] == 'error when pinging healthcheck' && log['storage'] == node
|
||||
health_check_failure_message?(log['msg']) && log['storage'] == node
|
||||
rescue JSON::ParserError
|
||||
# Ignore lines that can't be parsed as JSON
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
module QA
|
||||
RSpec.describe 'Create' do
|
||||
context 'Gitaly', :orchestrated, :mtls, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/324622', type: :investigating } do
|
||||
context 'Gitaly', :orchestrated, :mtls do
|
||||
describe 'Using mTLS' do
|
||||
let(:intial_commit_message) { 'Initial commit' }
|
||||
let(:first_added_commit_message) { 'commit over git' }
|
||||
|
|
|
|||
|
|
@ -52,7 +52,8 @@ module GitalyTest
|
|||
'RUBYOPT' => nil,
|
||||
|
||||
# Git hooks can't run during tests as the internal API is not running.
|
||||
'GITALY_TESTING_NO_GIT_HOOKS' => "1"
|
||||
'GITALY_TESTING_NO_GIT_HOOKS' => "1",
|
||||
'GITALY_TESTING_ENABLE_ALL_FEATURE_FLAGS' => "true"
|
||||
}
|
||||
|
||||
env_hash
|
||||
|
|
|
|||
|
|
@ -17,9 +17,6 @@ import {
|
|||
fetchDiffFilesBatch,
|
||||
fetchDiffFilesMeta,
|
||||
fetchCoverageFiles,
|
||||
clearEtagPoll,
|
||||
stopCodequalityPolling,
|
||||
fetchCodequality,
|
||||
assignDiscussionsToDiff,
|
||||
removeDiscussionsFromDiff,
|
||||
startRenderDiffsQueue,
|
||||
|
|
@ -101,7 +98,6 @@ describe('DiffsStoreActions', () => {
|
|||
const endpointMetadata = '/diffs/set/endpoint/metadata';
|
||||
const endpointBatch = '/diffs/set/endpoint/batch';
|
||||
const endpointCoverage = '/diffs/set/coverage_reports';
|
||||
const endpointCodequality = '/diffs/set/codequality_diff';
|
||||
const projectPath = '/root/project';
|
||||
const dismissEndpoint = '/-/user_callouts';
|
||||
const showSuggestPopover = false;
|
||||
|
|
@ -113,7 +109,6 @@ describe('DiffsStoreActions', () => {
|
|||
endpointBatch,
|
||||
endpointMetadata,
|
||||
endpointCoverage,
|
||||
endpointCodequality,
|
||||
projectPath,
|
||||
dismissEndpoint,
|
||||
showSuggestPopover,
|
||||
|
|
@ -123,7 +118,6 @@ describe('DiffsStoreActions', () => {
|
|||
endpointBatch: '',
|
||||
endpointMetadata: '',
|
||||
endpointCoverage: '',
|
||||
endpointCodequality: '',
|
||||
projectPath: '',
|
||||
dismissEndpoint: '',
|
||||
showSuggestPopover: true,
|
||||
|
|
@ -136,7 +130,6 @@ describe('DiffsStoreActions', () => {
|
|||
endpointMetadata,
|
||||
endpointBatch,
|
||||
endpointCoverage,
|
||||
endpointCodequality,
|
||||
projectPath,
|
||||
dismissEndpoint,
|
||||
showSuggestPopover,
|
||||
|
|
@ -306,47 +299,6 @@ describe('DiffsStoreActions', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('fetchCodequality', () => {
|
||||
let mock;
|
||||
const endpointCodequality = '/fetch';
|
||||
|
||||
beforeEach(() => {
|
||||
mock = new MockAdapter(axios);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
stopCodequalityPolling();
|
||||
clearEtagPoll();
|
||||
});
|
||||
|
||||
it('should commit SET_CODEQUALITY_DATA with received response', (done) => {
|
||||
const data = {
|
||||
files: { 'app.js': [{ line: 1, description: 'Unexpected alert.', severity: 'minor' }] },
|
||||
};
|
||||
|
||||
mock.onGet(endpointCodequality).reply(200, { data });
|
||||
|
||||
testAction(
|
||||
fetchCodequality,
|
||||
{},
|
||||
{ endpointCodequality },
|
||||
[{ type: types.SET_CODEQUALITY_DATA, payload: { data } }],
|
||||
[],
|
||||
done,
|
||||
);
|
||||
});
|
||||
|
||||
it('should show flash on API error', (done) => {
|
||||
mock.onGet(endpointCodequality).reply(400);
|
||||
|
||||
testAction(fetchCodequality, {}, { endpointCodequality }, [], [], () => {
|
||||
expect(createFlash).toHaveBeenCalledTimes(1);
|
||||
expect(createFlash).toHaveBeenCalledWith(expect.stringMatching('Something went wrong'));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('setHighlightedRow', () => {
|
||||
it('should mark currently selected diff and set lineHash and fileHash of highlightedRow', () => {
|
||||
testAction(setHighlightedRow, 'ABC_123', {}, [
|
||||
|
|
|
|||
|
|
@ -376,26 +376,6 @@ describe('Diffs Module Getters', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('fileCodequalityDiff', () => {
|
||||
beforeEach(() => {
|
||||
Object.assign(localState.codequalityDiff, {
|
||||
files: { 'app.js': [{ line: 1, description: 'Unexpected alert.', severity: 'minor' }] },
|
||||
});
|
||||
});
|
||||
|
||||
it('returns empty array when no codequality data is available', () => {
|
||||
Object.assign(localState.codequalityDiff, {});
|
||||
|
||||
expect(getters.fileCodequalityDiff(localState)('test.js')).toEqual([]);
|
||||
});
|
||||
|
||||
it('returns array when codequality data is available for given file', () => {
|
||||
expect(getters.fileCodequalityDiff(localState)('app.js')).toEqual([
|
||||
{ line: 1, description: 'Unexpected alert.', severity: 'minor' },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('suggestionCommitMessage', () => {
|
||||
let rootState;
|
||||
|
||||
|
|
|
|||
|
|
@ -115,19 +115,6 @@ describe('DiffsStoreMutations', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('SET_CODEQUALITY_DATA', () => {
|
||||
it('should set codequality data', () => {
|
||||
const state = { codequalityDiff: {} };
|
||||
const codequality = {
|
||||
files: { 'app.js': [{ line: 1, description: 'Unexpected alert.', severity: 'minor' }] },
|
||||
};
|
||||
|
||||
mutations[types.SET_CODEQUALITY_DATA](state, codequality);
|
||||
|
||||
expect(state.codequalityDiff).toEqual(codequality);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SET_DIFF_VIEW_TYPE', () => {
|
||||
it('should set diff view type properly', () => {
|
||||
const state = {};
|
||||
|
|
|
|||
|
|
@ -4,5 +4,47 @@
|
|||
---
|
||||
- name: bold
|
||||
markdown: '**bold**'
|
||||
- name: code
|
||||
- name: emphasis
|
||||
markdown: '_emphasized text_'
|
||||
- name: inline_code
|
||||
markdown: '`code`'
|
||||
- name: link
|
||||
markdown: '[GitLab](https://gitlab.com)'
|
||||
- name: code_block
|
||||
markdown: |-
|
||||
```javascript
|
||||
console.log('hello world')
|
||||
```
|
||||
- name: headings
|
||||
markdown: |-
|
||||
# Heading 1
|
||||
|
||||
## Heading 2
|
||||
|
||||
### Heading 3
|
||||
|
||||
#### Heading 4
|
||||
|
||||
##### Heading 5
|
||||
|
||||
###### Heading 6
|
||||
- name: blockquote
|
||||
markdown: |-
|
||||
> This is a blockquote
|
||||
>
|
||||
> This is another one
|
||||
- name: thematic_break
|
||||
markdown: |-
|
||||
---
|
||||
- name: bullet_list
|
||||
markdown: |-
|
||||
* list item 1
|
||||
* list item 2
|
||||
* embedded list item 3
|
||||
- name: ordered_list
|
||||
markdown: |-
|
||||
1. list item 1
|
||||
2. list item 2
|
||||
3. list item 3
|
||||
- name: image
|
||||
markdown: ''
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import ExperimentTracking from '~/experimentation/experiment_tracking';
|
||||
import PipelinesCiTemplate from '~/pipelines/components/pipelines_list/pipelines_ci_templates.vue';
|
||||
|
||||
const addCiYmlPath = "/-/new/master?commit_message='Add%20.gitlab-ci.yml'";
|
||||
|
|
@ -8,6 +9,8 @@ const suggestedCiTemplates = [
|
|||
{ name: 'C++', logo: '/assets/illustrations/logos/c_plus_plus.svg' },
|
||||
];
|
||||
|
||||
jest.mock('~/experimentation/experiment_tracking');
|
||||
|
||||
describe('Pipelines CI Templates', () => {
|
||||
let wrapper;
|
||||
|
||||
|
|
@ -81,4 +84,28 @@ describe('Pipelines CI Templates', () => {
|
|||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('tracking', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = createWrapper();
|
||||
});
|
||||
|
||||
it('sends an event when template is clicked', () => {
|
||||
findTemplateLinks().at(0).vm.$emit('click');
|
||||
|
||||
expect(ExperimentTracking).toHaveBeenCalledWith('pipeline_empty_state_templates', {
|
||||
label: 'Android',
|
||||
});
|
||||
expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith('template_clicked');
|
||||
});
|
||||
|
||||
it('sends an event when Hello-World template is clicked', () => {
|
||||
findTestTemplateLinks().at(0).vm.$emit('click');
|
||||
|
||||
expect(ExperimentTracking).toHaveBeenCalledWith('pipeline_empty_state_templates', {
|
||||
label: 'Hello-World',
|
||||
});
|
||||
expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith('template_clicked');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -389,20 +389,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when FF ci_workflow_rules_variables is disabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_workflow_rules_variables: false)
|
||||
end
|
||||
|
||||
it 'does not return job_variables and root_variables_inheritance' do
|
||||
expect(entry.value).to include(
|
||||
variables: { 'A' => 'job', 'B' => 'job' }
|
||||
)
|
||||
expect(entry.value).not_to have_key(:job_variables)
|
||||
expect(entry.value).not_to have_key(:root_variables_inheritance)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when root yaml variables are used' do
|
||||
let(:variables) do
|
||||
Gitlab::Ci::Config::Entry::Variables.new(
|
||||
|
|
@ -520,21 +506,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
|
|||
root_variables_inheritance: true
|
||||
)
|
||||
end
|
||||
|
||||
context 'when FF ci_workflow_rules_variables is disabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_workflow_rules_variables: false)
|
||||
end
|
||||
|
||||
it 'does not return job_variables and root_variables_inheritance' do
|
||||
expect(entry.value).to eq(
|
||||
name: :rspec,
|
||||
stage: 'test',
|
||||
only: { refs: %w[branches tags] },
|
||||
variables: {}
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -107,54 +107,5 @@ RSpec.describe Gitlab::Ci::Config::Normalizer::MatrixStrategy do
|
|||
['test: [aws, app1]', 'test: [aws, app2]', 'test: [gcp, app]', 'test: [ovh, app]']
|
||||
)
|
||||
end
|
||||
|
||||
context 'when the FF ci_workflow_rules_variables is disabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_workflow_rules_variables: false)
|
||||
end
|
||||
|
||||
it 'excludes job_variables' do
|
||||
expect(subject.map(&:attributes)).to match_array(
|
||||
[
|
||||
{
|
||||
name: 'test: [aws, app1]',
|
||||
instance: 1,
|
||||
parallel: { total: 4 },
|
||||
variables: {
|
||||
'PROVIDER' => 'aws',
|
||||
'STACK' => 'app1'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'test: [aws, app2]',
|
||||
instance: 2,
|
||||
parallel: { total: 4 },
|
||||
variables: {
|
||||
'PROVIDER' => 'aws',
|
||||
'STACK' => 'app2'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'test: [ovh, app]',
|
||||
instance: 3,
|
||||
parallel: { total: 4 },
|
||||
variables: {
|
||||
'PROVIDER' => 'ovh',
|
||||
'STACK' => 'app'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'test: [gcp, app]',
|
||||
instance: 4,
|
||||
parallel: { total: 4 },
|
||||
variables: {
|
||||
'PROVIDER' => 'gcp',
|
||||
'STACK' => 'app'
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -151,26 +151,6 @@ RSpec.describe Gitlab::WebIde::Config::Entry::Terminal do
|
|||
}
|
||||
)
|
||||
end
|
||||
|
||||
context 'when FF ci_workflow_rules_variables is disabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_workflow_rules_variables: false)
|
||||
end
|
||||
|
||||
it 'returns correct value without job_variables' do
|
||||
expect(entry.value)
|
||||
.to eq(
|
||||
tag_list: ['webide'],
|
||||
yaml_variables: [{ key: 'KEY', value: 'value', public: true }],
|
||||
options: {
|
||||
image: { name: "ruby:2.5" },
|
||||
services: [{ name: "mysql" }],
|
||||
before_script: %w[ls pwd],
|
||||
script: ['sleep 100']
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,30 +2,28 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Milestone, 'Milestoneish' do
|
||||
let(:author) { create(:user) }
|
||||
let(:assignee) { create(:user) }
|
||||
let(:non_member) { create(:user) }
|
||||
let(:member) { create(:user) }
|
||||
let(:guest) { create(:user) }
|
||||
let(:admin) { create(:admin) }
|
||||
let(:project) { create(:project, :public) }
|
||||
let(:milestone) { create(:milestone, project: project) }
|
||||
let(:label1) { create(:label, project: project) }
|
||||
let(:label2) { create(:label, project: project) }
|
||||
let!(:issue) { create(:issue, project: project, milestone: milestone, assignees: [member], labels: [label1]) }
|
||||
let!(:security_issue_1) { create(:issue, :confidential, project: project, author: author, milestone: milestone, labels: [label2]) }
|
||||
let!(:security_issue_2) { create(:issue, :confidential, project: project, assignees: [assignee], milestone: milestone) }
|
||||
let!(:closed_issue_1) { create(:issue, :closed, project: project, milestone: milestone) }
|
||||
let!(:closed_issue_2) { create(:issue, :closed, project: project, milestone: milestone) }
|
||||
let!(:closed_security_issue_1) { create(:issue, :confidential, :closed, project: project, author: author, milestone: milestone) }
|
||||
let!(:closed_security_issue_2) { create(:issue, :confidential, :closed, project: project, assignees: [assignee], milestone: milestone) }
|
||||
let!(:closed_security_issue_3) { create(:issue, :confidential, :closed, project: project, author: author, milestone: milestone) }
|
||||
let!(:closed_security_issue_4) { create(:issue, :confidential, :closed, project: project, assignees: [assignee], milestone: milestone) }
|
||||
let!(:merge_request) { create(:merge_request, source_project: project, target_project: project, milestone: milestone) }
|
||||
let(:label_1) { create(:label, title: 'label_1', project: project, priority: 1) }
|
||||
let(:label_2) { create(:label, title: 'label_2', project: project, priority: 2) }
|
||||
let(:label_3) { create(:label, title: 'label_3', project: project) }
|
||||
RSpec.describe Milestone, 'Milestoneish', factory_default: :keep do
|
||||
let_it_be(:author) { create(:user) }
|
||||
let_it_be(:assignee) { create(:user) }
|
||||
let_it_be(:non_member) { create(:user) }
|
||||
let_it_be(:member) { create(:user) }
|
||||
let_it_be(:guest) { create(:user) }
|
||||
let_it_be(:admin) { create(:admin) }
|
||||
let_it_be(:project, reload: true) { create_default(:project, :public, :empty_repo).freeze }
|
||||
let_it_be(:milestone, refind: true) { create_default(:milestone, project: project) }
|
||||
let_it_be(:label1) { create(:label) }
|
||||
let_it_be(:label2) { create(:label) }
|
||||
let_it_be(:issue, reload: true) { create(:issue, milestone: milestone, assignees: [member], labels: [label1]) }
|
||||
let_it_be(:security_issue_1, reload: true) { create(:issue, :confidential, author: author, milestone: milestone, labels: [label2]) }
|
||||
let_it_be(:security_issue_2, reload: true) { create(:issue, :confidential, assignees: [assignee], milestone: milestone) }
|
||||
let_it_be(:closed_issue_1, reload: true) { create(:issue, :closed, milestone: milestone) }
|
||||
let_it_be(:closed_issue_2, reload: true) { create(:issue, :closed, milestone: milestone) }
|
||||
let_it_be(:closed_security_issue_1, reload: true) { create(:issue, :confidential, :closed, author: author, milestone: milestone) }
|
||||
let_it_be(:closed_security_issue_2, reload: true) { create(:issue, :confidential, :closed, assignees: [assignee], milestone: milestone) }
|
||||
let_it_be(:merge_request) { create(:merge_request, source_project: project, target_project: project, milestone: milestone) }
|
||||
let_it_be(:label_1) { create(:label, title: 'label_1', priority: 1) }
|
||||
let_it_be(:label_2) { create(:label, title: 'label_2', priority: 2) }
|
||||
let_it_be(:label_3) { create(:label, title: 'label_3') }
|
||||
|
||||
before do
|
||||
project.add_developer(member)
|
||||
|
|
@ -63,7 +61,7 @@ RSpec.describe Milestone, 'Milestoneish' do
|
|||
end
|
||||
end
|
||||
|
||||
context 'attributes visibility' do
|
||||
context 'with attributes visibility' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
let(:users) do
|
||||
|
|
@ -167,8 +165,6 @@ RSpec.describe Milestone, 'Milestoneish' do
|
|||
end
|
||||
|
||||
describe '#merge_requests_visible_to_user' do
|
||||
let(:merge_request) { create(:merge_request, source_project: project, milestone: milestone) }
|
||||
|
||||
context 'when project is private' do
|
||||
before do
|
||||
project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
|
||||
|
|
@ -211,10 +207,11 @@ RSpec.describe Milestone, 'Milestoneish' do
|
|||
end
|
||||
|
||||
context 'when milestone is at parent level group' do
|
||||
let(:parent_group) { create(:group) }
|
||||
let(:group) { create(:group, parent: parent_group) }
|
||||
let(:project) { create(:project, namespace: group) }
|
||||
let(:milestone) { create(:milestone, group: parent_group) }
|
||||
let_it_be(:parent_group) { create(:group) }
|
||||
let_it_be(:group) { create(:group, parent: parent_group) }
|
||||
let_it_be(:project) { create(:project, :empty_repo, namespace: group) }
|
||||
let_it_be(:milestone) { create(:milestone, group: parent_group) }
|
||||
let_it_be(:merge_request) { create(:merge_request, source_project: project, milestone: milestone) }
|
||||
|
||||
it 'does not return any merge request for a non member' do
|
||||
merge_requests = milestone.merge_requests_visible_to_user(non_member)
|
||||
|
|
@ -243,7 +240,7 @@ RSpec.describe Milestone, 'Milestoneish' do
|
|||
end
|
||||
|
||||
describe '#percent_complete', :use_clean_rails_memory_store_caching do
|
||||
context 'division by zero' do
|
||||
context 'with division by zero' do
|
||||
let(:new_milestone) { build_stubbed(:milestone) }
|
||||
|
||||
it { expect(new_milestone.percent_complete).to eq(0) }
|
||||
|
|
@ -252,13 +249,13 @@ RSpec.describe Milestone, 'Milestoneish' do
|
|||
|
||||
describe '#closed_issues_count' do
|
||||
it 'counts all closed issues including confidential' do
|
||||
expect(milestone.closed_issues_count).to eq 6
|
||||
expect(milestone.closed_issues_count).to eq 4
|
||||
end
|
||||
end
|
||||
|
||||
describe '#total_issues_count' do
|
||||
it 'counts all issues including confidential' do
|
||||
expect(milestone.total_issues_count).to eq 9
|
||||
expect(milestone.total_issues_count).to eq 7
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe MergeRequests::ResolveTodosService do
|
||||
let_it_be(:merge_request) { create(:merge_request) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
let(:service) { described_class.new(merge_request, user) }
|
||||
|
||||
describe '#async_execute' do
|
||||
def async_execute
|
||||
service.async_execute
|
||||
end
|
||||
|
||||
it 'performs MergeRequests::ResolveTodosWorker asynchronously' do
|
||||
expect(MergeRequests::ResolveTodosWorker)
|
||||
.to receive(:perform_async)
|
||||
.with(
|
||||
merge_request.id,
|
||||
user.id
|
||||
)
|
||||
|
||||
async_execute
|
||||
end
|
||||
|
||||
context 'when resolve_merge_request_todos_async feature is disabled' do
|
||||
before do
|
||||
stub_feature_flags(resolve_merge_request_todos_async: false)
|
||||
end
|
||||
|
||||
it 'calls #execute' do
|
||||
expect(service).to receive(:execute)
|
||||
|
||||
async_execute
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#execute' do
|
||||
it 'marks pending todo as done' do
|
||||
pending_todo = create(:todo, :pending, user: user, project: merge_request.project, target: merge_request)
|
||||
|
||||
service.execute
|
||||
|
||||
expect(pending_todo.reload).to be_done
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -590,48 +590,54 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
|
|||
let!(:pending_todo) { create(:todo, :assigned, user: user, project: project, target: merge_request, author: user2) }
|
||||
|
||||
context 'when the title change' do
|
||||
before do
|
||||
it 'calls MergeRequest::ResolveTodosService#async_execute' do
|
||||
expect_next_instance_of(MergeRequests::ResolveTodosService, merge_request, user) do |service|
|
||||
expect(service).to receive(:async_execute)
|
||||
end
|
||||
|
||||
update_merge_request({ title: 'New title' })
|
||||
end
|
||||
|
||||
it 'marks pending todos as done' do
|
||||
expect(pending_todo.reload).to be_done
|
||||
end
|
||||
|
||||
it 'does not create any new todos' do
|
||||
update_merge_request({ title: 'New title' })
|
||||
|
||||
expect(Todo.count).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the description change' do
|
||||
before do
|
||||
it 'calls MergeRequest::ResolveTodosService#async_execute' do
|
||||
expect_next_instance_of(MergeRequests::ResolveTodosService, merge_request, user) do |service|
|
||||
expect(service).to receive(:async_execute)
|
||||
end
|
||||
|
||||
update_merge_request({ description: "Also please fix #{user2.to_reference} #{user3.to_reference}" })
|
||||
end
|
||||
|
||||
it 'marks pending todos as done' do
|
||||
expect(pending_todo.reload).to be_done
|
||||
end
|
||||
|
||||
it 'creates only 1 new todo' do
|
||||
update_merge_request({ description: "Also please fix #{user2.to_reference} #{user3.to_reference}" })
|
||||
|
||||
expect(Todo.count).to eq(2)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when is reassigned' do
|
||||
before do
|
||||
update_merge_request({ assignee_ids: [user2.id] })
|
||||
end
|
||||
it 'calls MergeRequest::ResolveTodosService#async_execute' do
|
||||
expect_next_instance_of(MergeRequests::ResolveTodosService, merge_request, user) do |service|
|
||||
expect(service).to receive(:async_execute)
|
||||
end
|
||||
|
||||
it 'marks previous assignee pending todos as done' do
|
||||
expect(pending_todo.reload).to be_done
|
||||
update_merge_request({ assignee_ids: [user2.id] })
|
||||
end
|
||||
end
|
||||
|
||||
context 'when reviewers gets changed' do
|
||||
it 'marks pending todo as done' do
|
||||
update_merge_request({ reviewer_ids: [user2.id] })
|
||||
it 'calls MergeRequest::ResolveTodosService#async_execute' do
|
||||
expect_next_instance_of(MergeRequests::ResolveTodosService, merge_request, user) do |service|
|
||||
expect(service).to receive(:async_execute)
|
||||
end
|
||||
|
||||
expect(pending_todo.reload).to be_done
|
||||
update_merge_request({ reviewer_ids: [user2.id] })
|
||||
end
|
||||
|
||||
it 'creates a pending todo for new review request' do
|
||||
|
|
@ -709,10 +715,12 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
it 'marks pending todos as done' do
|
||||
update_merge_request({ milestone: create(:milestone, project: project) })
|
||||
it 'calls MergeRequests::ResolveTodosService#async_execute' do
|
||||
expect_next_instance_of(MergeRequests::ResolveTodosService, merge_request, user) do |service|
|
||||
expect(service).to receive(:async_execute)
|
||||
end
|
||||
|
||||
expect(pending_todo.reload).to be_done
|
||||
update_merge_request({ milestone: create(:milestone, project: project) })
|
||||
end
|
||||
|
||||
it 'sends notifications for subscribers of changed milestone', :sidekiq_might_not_need_inline do
|
||||
|
|
@ -726,17 +734,19 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
|
|||
end
|
||||
|
||||
context 'when the labels change' do
|
||||
before do
|
||||
travel_to(1.minute.from_now) do
|
||||
update_merge_request({ label_ids: [label.id] })
|
||||
it 'calls MergeRequests::ResolveTodosService#async_execute' do
|
||||
expect_next_instance_of(MergeRequests::ResolveTodosService, merge_request, user) do |service|
|
||||
expect(service).to receive(:async_execute)
|
||||
end
|
||||
end
|
||||
|
||||
it 'marks pending todos as done' do
|
||||
expect(pending_todo.reload).to be_done
|
||||
update_merge_request({ label_ids: [label.id] })
|
||||
end
|
||||
|
||||
it 'updates updated_at' do
|
||||
travel_to(1.minute.from_now) do
|
||||
update_merge_request({ label_ids: [label.id] })
|
||||
end
|
||||
|
||||
expect(merge_request.reload.updated_at).to be > Time.current
|
||||
end
|
||||
end
|
||||
|
|
@ -751,24 +761,26 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
|
|||
end
|
||||
|
||||
context 'when the target branch change' do
|
||||
before do
|
||||
update_merge_request({ target_branch: 'target' })
|
||||
end
|
||||
it 'calls MergeRequests::ResolveTodosService#async_execute' do
|
||||
expect_next_instance_of(MergeRequests::ResolveTodosService, merge_request, user) do |service|
|
||||
expect(service).to receive(:async_execute)
|
||||
end
|
||||
|
||||
it 'marks pending todos as done' do
|
||||
expect(pending_todo.reload).to be_done
|
||||
update_merge_request({ target_branch: 'target' })
|
||||
end
|
||||
end
|
||||
|
||||
context 'when auto merge is enabled and target branch changed' do
|
||||
before do
|
||||
AutoMergeService.new(project, user, { sha: merge_request.diff_head_sha }).execute(merge_request, AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
|
||||
|
||||
update_merge_request({ target_branch: 'target' })
|
||||
end
|
||||
|
||||
it 'marks pending todos as done' do
|
||||
expect(pending_todo.reload).to be_done
|
||||
it 'calls MergeRequests::ResolveTodosService#async_execute' do
|
||||
expect_next_instance_of(MergeRequests::ResolveTodosService, merge_request, user) do |service|
|
||||
expect(service).to receive(:async_execute)
|
||||
end
|
||||
|
||||
update_merge_request({ target_branch: 'target' })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe MergeRequests::ResolveTodosWorker do
|
||||
include AfterNextHelpers
|
||||
|
||||
let_it_be(:merge_request) { create(:merge_request) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
let(:worker) { described_class.new }
|
||||
|
||||
it_behaves_like 'an idempotent worker' do
|
||||
let(:job_args) { [merge_request.id, user.id] }
|
||||
end
|
||||
|
||||
describe '#perform' do
|
||||
it 'calls MergeRequests::ResolveTodosService#execute' do
|
||||
expect_next(::MergeRequests::ResolveTodosService, merge_request, user)
|
||||
.to receive(:execute)
|
||||
|
||||
worker.perform(merge_request.id, user.id)
|
||||
end
|
||||
|
||||
context 'with a non-existing merge request' do
|
||||
it 'does nothing' do
|
||||
expect(::MergeRequests::ResolveTodosService).not_to receive(:new)
|
||||
|
||||
worker.perform(non_existing_record_id, user.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a non-existing user' do
|
||||
it 'does nothing' do
|
||||
expect(::MergeRequests::ResolveTodosService).not_to receive(:new)
|
||||
|
||||
worker.perform(merge_request.id, non_existing_record_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
40
yarn.lock
40
yarn.lock
|
|
@ -4703,10 +4703,10 @@ eslint-plugin-jest@^23.8.2:
|
|||
dependencies:
|
||||
"@typescript-eslint/experimental-utils" "^2.5.0"
|
||||
|
||||
eslint-plugin-no-jquery@2.5.0:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-2.5.0.tgz#6c12e3aae172bfd3363b7ac8c3f3e944704867f4"
|
||||
integrity sha512-RrQ380mUJJKdjgpQ/tZAJ3B3W1n3LbVmULooS2Pv5pUDcc5uVHVSJMTdUlsbvQyfo6hWP2LJ4FbOoDzENWcF7A==
|
||||
eslint-plugin-no-jquery@2.6.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-2.6.0.tgz#7892cb7c086f7813156bca6bc48429825428e9eb"
|
||||
integrity sha512-xC7pbNHJMdyxqhzcNMRrmC5/tbt1T4KCKXjOqUpKm/CaRryGKS5iWztzWPrL0KwyI3R3ub6goHFmIQS19f+mZA==
|
||||
|
||||
eslint-plugin-promise@^4.2.1:
|
||||
version "4.2.1"
|
||||
|
|
@ -4761,10 +4761,10 @@ eslint-visitor-keys@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
|
||||
integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
|
||||
|
||||
eslint@7.21.0:
|
||||
version "7.21.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.21.0.tgz#4ecd5b8c5b44f5dedc9b8a110b01bbfeb15d1c83"
|
||||
integrity sha512-W2aJbXpMNofUp0ztQaF40fveSsJBjlSCSWpy//gzfTvwC+USs/nceBrKmlJOiM8r1bLwP2EuYkCqArn/6QTIgg==
|
||||
eslint@7.24.0:
|
||||
version "7.24.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.24.0.tgz#2e44fa62d93892bfdb100521f17345ba54b8513a"
|
||||
integrity sha512-k9gaHeHiFmGCDQ2rEfvULlSLruz6tgfA8DEn+rY9/oYPFFTlz55mM/Q/Rij1b2Y42jwZiK3lXvNTw6w6TXzcKQ==
|
||||
dependencies:
|
||||
"@babel/code-frame" "7.12.11"
|
||||
"@eslint/eslintrc" "^0.4.0"
|
||||
|
|
@ -4783,7 +4783,7 @@ eslint@7.21.0:
|
|||
file-entry-cache "^6.0.1"
|
||||
functional-red-black-tree "^1.0.1"
|
||||
glob-parent "^5.0.0"
|
||||
globals "^12.1.0"
|
||||
globals "^13.6.0"
|
||||
ignore "^4.0.6"
|
||||
import-fresh "^3.0.0"
|
||||
imurmurhash "^0.1.4"
|
||||
|
|
@ -4791,7 +4791,7 @@ eslint@7.21.0:
|
|||
js-yaml "^3.13.1"
|
||||
json-stable-stringify-without-jsonify "^1.0.1"
|
||||
levn "^0.4.1"
|
||||
lodash "^4.17.20"
|
||||
lodash "^4.17.21"
|
||||
minimatch "^3.0.4"
|
||||
natural-compare "^1.4.0"
|
||||
optionator "^0.9.1"
|
||||
|
|
@ -5619,6 +5619,13 @@ globals@^12.1.0:
|
|||
dependencies:
|
||||
type-fest "^0.8.1"
|
||||
|
||||
globals@^13.6.0:
|
||||
version "13.8.0"
|
||||
resolved "https://registry.yarnpkg.com/globals/-/globals-13.8.0.tgz#3e20f504810ce87a8d72e55aecf8435b50f4c1b3"
|
||||
integrity sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==
|
||||
dependencies:
|
||||
type-fest "^0.20.2"
|
||||
|
||||
globby@^11.0.2:
|
||||
version "11.0.2"
|
||||
resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.2.tgz#1af538b766a3b540ebfb58a32b2e2d5897321d83"
|
||||
|
|
@ -7833,10 +7840,10 @@ lodash.values@^4.3.0:
|
|||
resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-4.3.0.tgz#a3a6c2b0ebecc5c2cba1c17e6e620fe81b53d347"
|
||||
integrity sha1-o6bCsOvsxcLLocF+bmIP6BtT00c=
|
||||
|
||||
lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@~4.17.10:
|
||||
version "4.17.20"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
|
||||
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
|
||||
lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@~4.17.10:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
||||
log-symbols@^2.1.0:
|
||||
version "2.2.0"
|
||||
|
|
@ -11781,6 +11788,11 @@ type-fest@^0.18.0:
|
|||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f"
|
||||
integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==
|
||||
|
||||
type-fest@^0.20.2:
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
|
||||
integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
|
||||
|
||||
type-fest@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b"
|
||||
|
|
|
|||
Loading…
Reference in New Issue