Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-01-11 21:10:36 +00:00
parent dcacb5daf7
commit a6c51b8876
55 changed files with 255 additions and 135 deletions

View File

@ -250,10 +250,10 @@ Dangerfile @gl-quality/eng-prod
/ee/spec/lib/gitlab/code_owners/ @reprazent @kerrizor @garyh /ee/spec/lib/gitlab/code_owners/ @reprazent @kerrizor @garyh
/doc/user/project/code_owners.md @reprazent @kerrizor @garyh /doc/user/project/code_owners.md @reprazent @kerrizor @garyh
[Product Analytics] [Product Intelligence]
/ee/lib/gitlab/usage_data_counters/ @gitlab-org/growth/product_analytics/engineers /ee/lib/gitlab/usage_data_counters/ @gitlab-org/growth/product_intelligence/engineers
/ee/lib/ee/gitlab/usage_data.rb @gitlab-org/growth/product_analytics/engineers /ee/lib/ee/gitlab/usage_data.rb @gitlab-org/growth/product_intelligence/engineers
/lib/gitlab/grafana_embed_usage_data.rb @gitlab-org/growth/product_analytics/engineers /lib/gitlab/grafana_embed_usage_data.rb @gitlab-org/growth/product_intelligence/engineers
/lib/gitlab/usage_data.rb @gitlab-org/growth/product_analytics/engineers /lib/gitlab/usage_data.rb @gitlab-org/growth/product_intelligence/engineers
/lib/gitlab/cycle_analytics/usage_data.rb @gitlab-org/growth/product_analytics/engineers /lib/gitlab/cycle_analytics/usage_data.rb @gitlab-org/growth/product_intelligence/engineers
/lib/gitlab/usage_data_counters/ @gitlab-org/growth/product_analytics/engineers /lib/gitlab/usage_data_counters/ @gitlab-org/growth/product_intelligence/engineers

View File

@ -40,6 +40,11 @@ export default {
directives: { directives: {
GlTooltip, GlTooltip,
}, },
inject: {
gitlabAlertFields: {
default: gitlabFieldsMock,
},
},
props: { props: {
payloadFields: { payloadFields: {
type: Array, type: Array,
@ -57,11 +62,6 @@ export default {
gitlabFields: this.gitlabAlertFields, gitlabFields: this.gitlabAlertFields,
}; };
}, },
inject: {
gitlabAlertFields: {
default: gitlabFieldsMock,
},
},
computed: { computed: {
mappingData() { mappingData() {
return this.gitlabFields.map((gitlabField) => { return this.gitlabFields.map((gitlabField) => {

View File

@ -117,6 +117,7 @@ export default {
directives: { directives: {
GlModal: GlModalDirective, GlModal: GlModalDirective,
}, },
mixins: [glFeatureFlagsMixin()],
inject: { inject: {
generic: { generic: {
default: {}, default: {},
@ -125,7 +126,6 @@ export default {
default: {}, default: {},
}, },
}, },
mixins: [glFeatureFlagsMixin()],
props: { props: {
loading: { loading: {
type: Boolean, type: Boolean,

View File

@ -35,6 +35,9 @@ export default (el) => {
return new Vue({ return new Vue({
el, el,
components: {
AlertSettingsWrapper,
},
provide: { provide: {
prometheus: { prometheus: {
active: parseBoolean(prometheusActivated), active: parseBoolean(prometheusActivated),
@ -56,9 +59,6 @@ export default (el) => {
multiIntegrations: parseBoolean(multiIntegrations), multiIntegrations: parseBoolean(multiIntegrations),
}, },
apolloProvider, apolloProvider,
components: {
AlertSettingsWrapper,
},
render(createElement) { render(createElement) {
return createElement('alert-settings-wrapper'); return createElement('alert-settings-wrapper');
}, },

View File

@ -16,6 +16,7 @@ export default {
directives: { directives: {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
inject: ['blobHash'],
props: { props: {
rawPath: { rawPath: {
type: String, type: String,
@ -32,7 +33,6 @@ export default {
default: false, default: false,
}, },
}, },
inject: ['blobHash'],
computed: { computed: {
downloadUrl() { downloadUrl() {
return `${this.rawPath}?inline=false`; return `${this.rawPath}?inline=false`;

View File

@ -8,12 +8,6 @@ export default {
components: { components: {
ApolloMutation, ApolloMutation,
}, },
props: {
filenames: {
type: Array,
required: true,
},
},
inject: { inject: {
projectPath: { projectPath: {
default: '', default: '',
@ -23,6 +17,12 @@ export default {
defaut: '', defaut: '',
}, },
}, },
props: {
filenames: {
type: Array,
required: true,
},
},
computed: { computed: {
projectQueryBody() { projectQueryBody() {
return { return {

View File

@ -21,6 +21,14 @@ export default {
DesignTodoButton, DesignTodoButton,
}, },
mixins: [glFeatureFlagsMixin()], mixins: [glFeatureFlagsMixin()],
inject: {
projectPath: {
default: '',
},
issueIid: {
default: '',
},
},
props: { props: {
design: { design: {
type: Object, type: Object,
@ -41,14 +49,6 @@ export default {
discussionWithOpenForm: '', discussionWithOpenForm: '',
}; };
}, },
inject: {
projectPath: {
default: '',
},
issueIid: {
default: '',
},
},
computed: { computed: {
discussions() { discussions() {
return extractDiscussions(this.design.discussions); return extractDiscussions(this.design.discussions);

View File

@ -13,12 +13,6 @@ export default {
TodoButton, TodoButton,
}, },
mixins: [allVersionsMixin], mixins: [allVersionsMixin],
props: {
design: {
type: Object,
required: true,
},
},
inject: { inject: {
projectPath: { projectPath: {
default: '', default: '',
@ -27,6 +21,12 @@ export default {
default: '', default: '',
}, },
}, },
props: {
design: {
type: Object,
required: true,
},
},
data() { data() {
return { return {
todoLoading: false, todoLoading: false,

View File

@ -18,6 +18,14 @@ export default {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
mixins: [timeagoMixin], mixins: [timeagoMixin],
inject: {
projectPath: {
default: '',
},
issueIid: {
default: '',
},
},
props: { props: {
id: { id: {
type: String, type: String,
@ -58,14 +66,6 @@ export default {
}, },
}; };
}, },
inject: {
projectPath: {
default: '',
},
issueIid: {
default: '',
},
},
apollo: { apollo: {
permissions: { permissions: {
query: permissionsQuery, query: permissionsQuery,

View File

@ -57,6 +57,27 @@ export default {
DesignSidebar, DesignSidebar,
}, },
mixins: [allVersionsMixin, glFeatureFlagsMixin()], mixins: [allVersionsMixin, glFeatureFlagsMixin()],
beforeRouteUpdate(to, from, next) {
// reset scale when the active design changes
this.scale = DEFAULT_SCALE;
next();
},
beforeRouteEnter(to, from, next) {
const pageEl = getPageLayoutElement();
if (pageEl) {
pageEl.classList.add(...DESIGN_DETAIL_LAYOUT_CLASSLIST);
}
next();
},
beforeRouteLeave(to, from, next) {
const pageEl = getPageLayoutElement();
if (pageEl) {
pageEl.classList.remove(...DESIGN_DETAIL_LAYOUT_CLASSLIST);
}
next();
},
props: { props: {
id: { id: {
type: String, type: String,
@ -161,11 +182,6 @@ export default {
beforeDestroy() { beforeDestroy() {
Mousetrap.unbind('esc', this.closeDesign); Mousetrap.unbind('esc', this.closeDesign);
}, },
beforeRouteUpdate(to, from, next) {
// reset scale when the active design changes
this.scale = DEFAULT_SCALE;
next();
},
methods: { methods: {
addImageDiffNoteToStore(store, { data: { createImageDiffNote } }) { addImageDiffNoteToStore(store, { data: { createImageDiffNote } }) {
updateStoreAfterAddImageDiffNote( updateStoreAfterAddImageDiffNote(
@ -296,22 +312,6 @@ export default {
this.resolvedDiscussionsExpanded = !this.resolvedDiscussionsExpanded; this.resolvedDiscussionsExpanded = !this.resolvedDiscussionsExpanded;
}, },
}, },
beforeRouteEnter(to, from, next) {
const pageEl = getPageLayoutElement();
if (pageEl) {
pageEl.classList.add(...DESIGN_DETAIL_LAYOUT_CLASSLIST);
}
next();
},
beforeRouteLeave(to, from, next) {
const pageEl = getPageLayoutElement();
if (pageEl) {
pageEl.classList.remove(...DESIGN_DETAIL_LAYOUT_CLASSLIST);
}
next();
},
createImageDiffNoteMutation, createImageDiffNoteMutation,
DESIGNS_ROUTE_NAME, DESIGNS_ROUTE_NAME,
}; };

View File

@ -72,6 +72,10 @@ export default {
update: (data) => data.project.issue.userPermissions, update: (data) => data.project.issue.userPermissions,
}, },
}, },
beforeRouteUpdate(to, from, next) {
this.selectedDesigns = [];
next();
},
data() { data() {
return { return {
permissions: { permissions: {
@ -324,10 +328,6 @@ export default {
this.reorderedDesigns = designs; this.reorderedDesigns = designs;
}, },
}, },
beforeRouteUpdate(to, from, next) {
this.selectedDesigns = [];
next();
},
dragOptions: { dragOptions: {
animation: 200, animation: 200,
ghostClass: 'gl-visibility-hidden', ghostClass: 'gl-visibility-hidden',

View File

@ -31,6 +31,13 @@ export default {
directives: { directives: {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
inject: [
'projectName',
'featureFlagsHelpPagePath',
'unleashApiUrl',
'featureFlagsClientExampleHelpPagePath',
'featureFlagsClientLibrariesHelpPagePath',
],
props: { props: {
instanceId: { instanceId: {
@ -55,13 +62,6 @@ export default {
required: true, required: true,
}, },
}, },
inject: [
'projectName',
'featureFlagsHelpPagePath',
'unleashApiUrl',
'featureFlagsClientExampleHelpPagePath',
'featureFlagsClientLibrariesHelpPagePath',
],
translations: { translations: {
cancelActionLabel: __('Close'), cancelActionLabel: __('Close'),
modalTitle: s__('FeatureFlags|Configure feature flags'), modalTitle: s__('FeatureFlags|Configure feature flags'),

View File

@ -31,6 +31,7 @@ export default {
GlButton, GlButton,
GlSearchBoxByType, GlSearchBoxByType,
}, },
inject: ['environmentsEndpoint'],
props: { props: {
value: { value: {
type: String, type: String,
@ -53,7 +54,6 @@ export default {
required: false, required: false,
}, },
}, },
inject: ['environmentsEndpoint'],
data() { data() {
return { return {
environmentSearch: this.value, environmentSearch: this.value,

View File

@ -3,6 +3,7 @@ import { GlAlert, GlBadge, GlEmptyState, GlLink, GlLoadingIcon, GlTab } from '@g
export default { export default {
components: { GlAlert, GlBadge, GlEmptyState, GlLink, GlLoadingIcon, GlTab }, components: { GlAlert, GlBadge, GlEmptyState, GlLink, GlLoadingIcon, GlTab },
inject: ['errorStateSvgPath', 'featureFlagsHelpPagePath'],
props: { props: {
title: { title: {
required: true, required: true,
@ -46,7 +47,6 @@ export default {
type: String, type: String,
}, },
}, },
inject: ['errorStateSvgPath', 'featureFlagsHelpPagePath'],
computed: { computed: {
itemCount() { itemCount() {
return this.count ?? 0; return this.count ?? 0;

View File

@ -17,13 +17,13 @@ export default {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
mixins: [glFeatureFlagMixin()], mixins: [glFeatureFlagMixin()],
inject: ['csrfToken'],
props: { props: {
featureFlags: { featureFlags: {
type: Array, type: Array,
required: true, required: true,
}, },
}, },
inject: ['csrfToken'],
data() { data() {
return { return {
deleteFeatureFlagUrl: null, deleteFeatureFlagUrl: null,

View File

@ -46,6 +46,11 @@ export default {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
mixins: [featureFlagsMixin()], mixins: [featureFlagsMixin()],
inject: {
featureFlagIssuesEndpoint: {
default: '',
},
},
props: { props: {
active: { active: {
type: Boolean, type: Boolean,
@ -86,11 +91,6 @@ export default {
default: LEGACY_FLAG, default: LEGACY_FLAG,
}, },
}, },
inject: {
featureFlagIssuesEndpoint: {
default: '',
},
},
translations: { translations: {
allEnvironmentsText: s__('FeatureFlags|* (All Environments)'), allEnvironmentsText: s__('FeatureFlags|* (All Environments)'),

View File

@ -11,6 +11,11 @@ export default {
i18n: { i18n: {
...JOB_RETRY_FORWARD_DEPLOYMENT_MODAL, ...JOB_RETRY_FORWARD_DEPLOYMENT_MODAL,
}, },
inject: {
retryOutdatedJobDocsUrl: {
default: '',
},
},
props: { props: {
modalId: { modalId: {
type: String, type: String,
@ -21,11 +26,6 @@ export default {
required: true, required: true,
}, },
}, },
inject: {
retryOutdatedJobDocsUrl: {
default: '',
},
},
data() { data() {
return { return {
primaryProps: { primaryProps: {

View File

@ -6,8 +6,8 @@ export default {
components: { components: {
EditorLite, EditorLite,
}, },
inheritAttrs: false,
inject: ['projectPath', 'projectNamespace'], inject: ['projectPath', 'projectNamespace'],
inheritAttrs: false,
props: { props: {
ciConfigPath: { ciConfigPath: {
type: String, type: String,

View File

@ -51,6 +51,9 @@ export default {
return `${actionIconDash} js-icon-${actionIconDash}`; return `${actionIconDash} js-icon-${actionIconDash}`;
}, },
}, },
errorCaptured(err, _vm, info) {
reportToSentry('action_component', `error: ${err}, info: ${info}`);
},
methods: { methods: {
/** /**
* The request should not be handled here. * The request should not be handled here.

View File

@ -3,6 +3,7 @@ import LinkedGraphWrapper from '../graph_shared/linked_graph_wrapper.vue';
import LinkedPipelinesColumn from './linked_pipelines_column.vue'; import LinkedPipelinesColumn from './linked_pipelines_column.vue';
import StageColumnComponent from './stage_column_component.vue'; import StageColumnComponent from './stage_column_component.vue';
import { DOWNSTREAM, MAIN, UPSTREAM } from './constants'; import { DOWNSTREAM, MAIN, UPSTREAM } from './constants';
import { reportToSentry } from './utils';
export default { export default {
name: 'PipelineGraph', name: 'PipelineGraph',
@ -68,6 +69,9 @@ export default {
return this.hasUpstreamPipelines ? this.pipeline.upstream : []; return this.hasUpstreamPipelines ? this.pipeline.upstream : [];
}, },
}, },
errorCaptured(err, _vm, info) {
reportToSentry(this.$options.name, `error: ${err}, info: ${info}`);
},
methods: { methods: {
setJob(jobName) { setJob(jobName) {
this.hoveredJobName = jobName; this.hoveredJobName = jobName;

View File

@ -5,6 +5,7 @@ import StageColumnComponentLegacy from './stage_column_component_legacy.vue';
import LinkedPipelinesColumnLegacy from './linked_pipelines_column_legacy.vue'; import LinkedPipelinesColumnLegacy from './linked_pipelines_column_legacy.vue';
import GraphBundleMixin from '../../mixins/graph_pipeline_bundle_mixin'; import GraphBundleMixin from '../../mixins/graph_pipeline_bundle_mixin';
import { UPSTREAM, DOWNSTREAM, MAIN } from './constants'; import { UPSTREAM, DOWNSTREAM, MAIN } from './constants';
import { reportToSentry } from './utils';
export default { export default {
name: 'PipelineGraphLegacy', name: 'PipelineGraphLegacy',
@ -94,6 +95,9 @@ export default {
return this.pipeline.project.id; return this.pipeline.project.id;
}, },
}, },
errorCaptured(err, _vm, info) {
reportToSentry(this.$options.name, `error: ${err}, info: ${info}`);
},
methods: { methods: {
capitalizeStageName(name) { capitalizeStageName(name) {
const escapedName = escape(name); const escapedName = escape(name);

View File

@ -76,6 +76,9 @@ export default {
mounted() { mounted() {
toggleQueryPollingByVisibility(this.$apollo.queries.pipeline); toggleQueryPollingByVisibility(this.$apollo.queries.pipeline);
}, },
errorCaptured(err, _vm, info) {
reportToSentry(this.$options.name, `error: ${err}, info: ${info}`);
},
methods: { methods: {
hideAlert() { hideAlert() {
this.showAlert = false; this.showAlert = false;

View File

@ -2,6 +2,7 @@
import { GlTooltipDirective } from '@gitlab/ui'; import { GlTooltipDirective } from '@gitlab/ui';
import CiIcon from '~/vue_shared/components/ci_icon.vue'; import CiIcon from '~/vue_shared/components/ci_icon.vue';
import JobItem from './job_item.vue'; import JobItem from './job_item.vue';
import { reportToSentry } from './utils';
/** /**
* Renders the dropdown for the pipeline graph. * Renders the dropdown for the pipeline graph.
@ -29,6 +30,9 @@ export default {
return `${name} - ${status.label}`; return `${name} - ${status.label}`;
}, },
}, },
errorCaptured(err, _vm, info) {
reportToSentry('job_group_dropdown', `error: ${err}, info: ${info}`);
},
methods: { methods: {
pipelineActionRequestComplete() { pipelineActionRequestComplete() {
this.$emit('pipelineActionRequestComplete'); this.$emit('pipelineActionRequestComplete');

View File

@ -6,6 +6,7 @@ import { sprintf } from '~/locale';
import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin'; import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
import { accessValue } from './accessors'; import { accessValue } from './accessors';
import { REST } from './constants'; import { REST } from './constants';
import { reportToSentry } from './utils';
/** /**
* Renders the badge for the pipeline graph and the job's dropdown. * Renders the badge for the pipeline graph and the job's dropdown.
@ -130,6 +131,9 @@ export default {
: this.cssClassJobName; : this.cssClassJobName;
}, },
}, },
errorCaptured(err, _vm, info) {
reportToSentry('job_item', `error: ${err}, info: ${info}`);
},
methods: { methods: {
hideTooltips() { hideTooltips() {
this.$root.$emit('bv::hide::tooltip'); this.$root.$emit('bv::hide::tooltip');

View File

@ -4,6 +4,7 @@ import CiStatus from '~/vue_shared/components/ci_icon.vue';
import { __, sprintf } from '~/locale'; import { __, sprintf } from '~/locale';
import { accessValue } from './accessors'; import { accessValue } from './accessors';
import { DOWNSTREAM, REST, UPSTREAM } from './constants'; import { DOWNSTREAM, REST, UPSTREAM } from './constants';
import { reportToSentry } from './utils';
export default { export default {
directives: { directives: {
@ -114,6 +115,9 @@ export default {
return this.isUpstream ? 'gl-left-0 gl-border-r-1!' : 'gl-right-0 gl-border-l-1!'; return this.isUpstream ? 'gl-left-0 gl-border-r-1!' : 'gl-right-0 gl-border-l-1!';
}, },
}, },
errorCaptured(err, _vm, info) {
reportToSentry('linked_pipeline', `error: ${err}, info: ${info}`);
},
methods: { methods: {
onClickLinkedPipeline() { onClickLinkedPipeline() {
this.hideTooltips(); this.hideTooltips();

View File

@ -1,6 +1,7 @@
<script> <script>
import LinkedPipeline from './linked_pipeline.vue'; import LinkedPipeline from './linked_pipeline.vue';
import { UPSTREAM } from './constants'; import { UPSTREAM } from './constants';
import { reportToSentry } from './utils';
export default { export default {
components: { components: {
@ -42,6 +43,9 @@ export default {
return this.type === UPSTREAM; return this.type === UPSTREAM;
}, },
}, },
errorCaptured(err, _vm, info) {
reportToSentry('linked_pipelines_column_legacy', `error: ${err}, info: ${info}`);
},
methods: { methods: {
onPipelineClick(downstreamNode, pipeline, index) { onPipelineClick(downstreamNode, pipeline, index) {
this.$emit('linkedPipelineClick', pipeline, index, downstreamNode); this.$emit('linkedPipelineClick', pipeline, index, downstreamNode);

View File

@ -6,6 +6,7 @@ import JobGroupDropdown from './job_group_dropdown.vue';
import ActionComponent from './action_component.vue'; import ActionComponent from './action_component.vue';
import { GRAPHQL } from './constants'; import { GRAPHQL } from './constants';
import { accessValue } from './accessors'; import { accessValue } from './accessors';
import { reportToSentry } from './utils';
export default { export default {
components: { components: {
@ -54,6 +55,9 @@ export default {
return !isEmpty(this.action); return !isEmpty(this.action);
}, },
}, },
errorCaptured(err, _vm, info) {
reportToSentry('stage_column_component', `error: ${err}, info: ${info}`);
},
methods: { methods: {
getGroupId(group) { getGroupId(group) {
return accessValue(GRAPHQL, 'groupId', group); return accessValue(GRAPHQL, 'groupId', group);

View File

@ -4,6 +4,7 @@ import stageColumnMixin from '../../mixins/stage_column_mixin';
import JobItem from './job_item.vue'; import JobItem from './job_item.vue';
import JobGroupDropdown from './job_group_dropdown.vue'; import JobGroupDropdown from './job_group_dropdown.vue';
import ActionComponent from './action_component.vue'; import ActionComponent from './action_component.vue';
import { reportToSentry } from './utils';
export default { export default {
components: { components: {
@ -52,6 +53,9 @@ export default {
return !isEmpty(this.action); return !isEmpty(this.action);
}, },
}, },
errorCaptured(err, _vm, info) {
reportToSentry('stage_column_component_legacy', `error: ${err}, info: ${info}`);
},
methods: { methods: {
groupId(group) { groupId(group) {
return `ci-badge-${escape(group.name)}`; return `ci-badge-${escape(group.name)}`;

View File

@ -11,6 +11,11 @@ export default {
directives: { directives: {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
inject: {
targetProjectFullPath: {
default: '',
},
},
props: { props: {
pipeline: { pipeline: {
type: Object, type: Object,
@ -25,11 +30,6 @@ export default {
required: true, required: true,
}, },
}, },
inject: {
targetProjectFullPath: {
default: '',
},
},
computed: { computed: {
user() { user() {
return this.pipeline.user; return this.pipeline.user;

View File

@ -10,6 +10,7 @@ import legacyPipelineHeader from './components/legacy_header_component.vue';
import eventHub from './event_hub'; import eventHub from './event_hub';
import TestReports from './components/test_reports/test_reports.vue'; import TestReports from './components/test_reports/test_reports.vue';
import createTestReportsStore from './stores/test_reports'; import createTestReportsStore from './stores/test_reports';
import { reportToSentry } from './components/graph/utils';
Vue.use(Translate); Vue.use(Translate);
@ -36,6 +37,9 @@ const createLegacyPipelinesDetailApp = (mediator) => {
mediator, mediator,
}; };
}, },
errorCaptured(err, _vm, info) {
reportToSentry('pipeline_details_bundle_legacy_details', `error: ${err}, info: ${info}`);
},
render(createElement) { render(createElement) {
return createElement('pipeline-graph-legacy', { return createElement('pipeline-graph-legacy', {
props: { props: {
@ -78,6 +82,9 @@ const createLegacyPipelineHeaderApp = (mediator) => {
eventHub.$off('headerPostAction', this.postAction); eventHub.$off('headerPostAction', this.postAction);
eventHub.$off('headerDeleteAction', this.deleteAction); eventHub.$off('headerDeleteAction', this.deleteAction);
}, },
errorCaptured(err, _vm, info) {
reportToSentry('pipeline_details_bundle_legacy', `error: ${err}, info: ${info}`);
},
methods: { methods: {
postAction(path) { postAction(path) {
this.mediator.service this.mediator.service

View File

@ -3,6 +3,7 @@ import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql'; import createDefaultClient from '~/lib/graphql';
import PipelineGraphWrapper from './components/graph/graph_component_wrapper.vue'; import PipelineGraphWrapper from './components/graph/graph_component_wrapper.vue';
import { GRAPHQL } from './components/graph/constants'; import { GRAPHQL } from './components/graph/constants';
import { reportToSentry } from './components/graph/utils';
Vue.use(VueApollo); Vue.use(VueApollo);
@ -28,6 +29,9 @@ const createPipelinesDetailApp = (selector, pipelineProjectPath, pipelineIid) =>
pipelineIid, pipelineIid,
dataMethod: GRAPHQL, dataMethod: GRAPHQL,
}, },
errorCaptured(err, _vm, info) {
reportToSentry('pipeline_details_graph', `error: ${err}, info: ${info}`);
},
render(createElement) { render(createElement) {
return createElement(PipelineGraphWrapper); return createElement(PipelineGraphWrapper);
}, },

View File

@ -1,3 +1,5 @@
- add_page_specific_style 'page_bundles/ci_status'
- breadcrumb_title _("Jobs") - breadcrumb_title _("Jobs")
- page_title _("Jobs") - page_title _("Jobs")

View File

@ -5,8 +5,8 @@
%div %div
- hook.class.triggers.each_value do |trigger| - hook.class.triggers.each_value do |trigger|
- if hook.public_send(trigger) - if hook.public_send(trigger)
%span.badge.badge-gray.deploy-project-label= trigger.to_s.titleize %span.gl-badge.gl-bg-gray-10.gl-mt-2.rounded.deploy-project-label= trigger.to_s.titleize
%span.badge.badge-gray %span.gl-badge.gl-bg-gray-10.gl-mt-2.rounded
= _('SSL Verification:') = _('SSL Verification:')
= hook.enable_ssl_verification ? _('enabled') : _('disabled') = hook.enable_ssl_verification ? _('enabled') : _('disabled')

View File

@ -7,12 +7,13 @@ class GitlabPerformanceBarStatsWorker
LEASE_TIMEOUT = 600 LEASE_TIMEOUT = 600
WORKER_DELAY = 120 WORKER_DELAY = 120
STATS_KEY = 'performance_bar_stats:pending_request_ids' STATS_KEY = 'performance_bar_stats:pending_request_ids'
STATS_KEY_EXPIRE = 30.minutes.to_i
feature_category :metrics feature_category :metrics
idempotent! idempotent!
def perform(lease_uuid) def perform(lease_uuid)
Gitlab::Redis::SharedState.with do |redis| Gitlab::Redis::Cache.with do |redis|
request_ids = fetch_request_ids(redis, lease_uuid) request_ids = fetch_request_ids(redis, lease_uuid)
stats = Gitlab::PerformanceBar::Stats.new(redis) stats = Gitlab::PerformanceBar::Stats.new(redis)

View File

@ -0,0 +1,5 @@
---
title: Fix jobs admin is missing CI status styles
merge_request: 51161
author: Kev @KevSlashNull
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Fix webhook badge color in darkmode
merge_request: 50943
author: Yogi (@yo)
type: fixed

View File

@ -1,8 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
PRODUCT_ANALYTICS_CHANGED_FILES_MESSAGE = <<~MSG CHANGED_FILES_MESSAGE = <<~MSG
For the following files, a review from the [Data team and Product Analytics team](https://gitlab.com/groups/gitlab-org/growth/product_analytics/engineers/-/group_members?with_inherited_permissions=exclude) is recommended For the following files, a review from the [Data team and Product Intelligence team](https://gitlab.com/groups/gitlab-org/growth/product_intelligence/engineers/-/group_members?with_inherited_permissions=exclude) is recommended
Please check the ~"product analytics" [guide](https://docs.gitlab.com/ee/development/product_analytics/usage_ping.html) and reach out to %<product_analytics_engineers_group>s group for a review. Please check the ~"product intelligence" [guide](https://docs.gitlab.com/ee/development/product_analytics/usage_ping.html) and reach out to %<engineers_group>s group for a review.
%<changed_files>s %<changed_files>s
@ -14,7 +14,7 @@ UPDATE_METRICS_DEFINITIONS_MESSAGE = <<~MSG
MSG MSG
PRODUCT_ANALYTICS_ENGINEERS_GROUP = '@gitlab-org/growth/product_analytics/engineers' ENGINEERS_GROUP = '@gitlab-org/growth/product_intelligence/engineers'
tracking_files = [ tracking_files = [
'lib/gitlab/tracking.rb', 'lib/gitlab/tracking.rb',
@ -33,16 +33,16 @@ changed_files = (usage_data_changed_files + snowplow_events_changed_files)
if changed_files.any? if changed_files.any?
mention = if helper.draft_mr? mention = if helper.draft_mr?
"`#{PRODUCT_ANALYTICS_ENGINEERS_GROUP}`" "`#{ENGINEERS_GROUP}`"
else else
PRODUCT_ANALYTICS_ENGINEERS_GROUP ENGINEERS_GROUP
end end
warn format(PRODUCT_ANALYTICS_CHANGED_FILES_MESSAGE, changed_files: helper.markdown_list(changed_files), product_analytics_engineers_group: mention) warn format(CHANGED_FILES_MESSAGE, changed_files: helper.markdown_list(changed_files), engineers_group: mention)
warn format(UPDATE_METRICS_DEFINITIONS_MESSAGE) unless helper.changed_files(/usage_ping\.md/).any? warn format(UPDATE_METRICS_DEFINITIONS_MESSAGE) unless helper.changed_files(/usage_ping\.md/).any?
product_analytics_labels = ['product analytics'] labels = ['product intelligence']
product_analytics_labels << 'product analytics::review pending' unless helper.mr_has_labels?('product analytics::reviewed') labels << 'product intelligence::review pending' unless helper.mr_has_labels?('product intelligence::approved')
markdown(helper.prepare_labels_for_mr(product_analytics_labels)) markdown(helper.prepare_labels_for_mr(labels))
end end

View File

@ -185,6 +185,8 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
## Snippets ## Snippets
The Snippets Notes API is intended for project-level snippets, and not for personal snippets.
### List all snippet notes ### List all snippet notes
Gets a list of all notes for a single snippet. Snippet notes are comments users can post to a snippet. Gets a list of all notes for a single snippet. Snippet notes are comments users can post to a snippet.

View File

@ -58,7 +58,7 @@ To enable pipelines for merged results for your project:
1. [Configure your CI/CD configuration file](../index.md#configuring-pipelines-for-merge-requests) 1. [Configure your CI/CD configuration file](../index.md#configuring-pipelines-for-merge-requests)
so that the pipeline or individual jobs run for merge requests. so that the pipeline or individual jobs run for merge requests.
1. Visit your project's **Settings > General** and expand **Merge requests**. 1. Visit your project's **Settings > General** and expand **Merge requests**.
1. Check **Enable merged results pipelines.**. 1. Check **Enable merged results pipelines**.
1. Click **Save changes**. 1. Click **Save changes**.
WARNING: WARNING:

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -349,18 +349,7 @@ Stages in pipeline mini graphs are collapsible. Hover your mouse over them and c
### Pipeline success and duration charts ### Pipeline success and duration charts
> - Introduced in GitLab 3.1.1 as Commit Stats, and later renamed to Pipeline Charts. Pipeline analytics are available on the [**CI/CD Analytics** page](../../user/analytics/ci_cd_analytics.md#pipeline-success-and-duration-charts).
> - [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/38318) to CI / CD Analytics in GitLab 12.8.
GitLab tracks the history of your pipeline successes and failures, as well as how long each pipeline ran. To view this information, go to **Analytics > CI / CD Analytics**.
View successful pipelines:
![Successful pipelines](img/pipelines_success_chart.png)
View pipeline duration history:
![Pipeline duration](img/pipelines_duration_chart.png)
### Pipeline badges ### Pipeline badges

View File

@ -349,6 +349,11 @@ in the GitLab UI to do this:
![Job artifacts browser button](img/job_artifacts_browser_button.png) ![Job artifacts browser button](img/job_artifacts_browser_button.png)
1. While on the details page of a merge request, you can see the download
icon for each job's artifacts on the right side of the pipeline widget:
![Job artifacts in Merge Request](img/job_artifacts_merge_request.png)
1. And finally, when browsing an archive you can see the download button at 1. And finally, when browsing an archive you can see the download button at
the top right corner: the top right corner:

View File

@ -281,13 +281,19 @@ Note that this data is completely separate from the [events tracking data](#impl
#### Add context #### Add context
You can add arbitrary context data in a hash which gets stored as part of the experiment user record. You can add arbitrary context data in a hash which gets stored as part of the experiment user record. New calls to the `record_experiment_user` with newer contexts get merged deeply into the existing context.
This data can then be used by data analytics dashboards. This data can then be used by data analytics dashboards.
```ruby ```ruby
before_action do before_action do
record_experiment_user(:signup_flow, foo: 42) record_experiment_user(:signup_flow, foo: 42, bar: { a: 22})
# context is { "foo" => 42, "bar" => { "a" => 22 }}
end end
# Additional contexts for newer record calls are merged deeply
record_experiment_user(:signup_flow, foo: 40, bar: { b: 2 }, thor: 3)
# context becomes { "foo" => 40, "bar" => { "a" => 22, "b" => 2 }, "thor" => 3}
``` ```
### Record experiment conversion event ### Record experiment conversion event
@ -339,7 +345,7 @@ https://gitlab.com/<EXPERIMENT_ENTRY_URL>?force_experiment=<EXPERIMENT_KEY>
### A cookie-based approach to force an experiment ### A cookie-based approach to force an experiment
It's possible to force the current user to be in the experiment group for <EXPERIMENT_KEY> It's possible to force the current user to be in the experiment group for `<EXPERIMENT_KEY>`
during the browser session by using your browser's developer tools: during the browser session by using your browser's developer tools:
```javascript ```javascript

View File

@ -0,0 +1,33 @@
---
stage: Release
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
---
# CI/CD Analytics
## Pipeline success and duration charts **(CORE)**
> - Introduced in GitLab 3.1.1 as Commit Stats, and later renamed to Pipeline Charts.
> - [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/38318) to CI/CD Analytics in GitLab 12.8.
GitLab tracks the history of your pipeline successes and failures, as well as how long each pipeline
ran. To view this information, go to **Analytics > CI/CD Analytics**.
View successful pipelines:
![Successful pipelines](img/pipelines_success_chart.png)
View pipeline duration history:
![Pipeline duration](img/pipelines_duration_chart.png)
## Deployment frequency charts **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/275991) in GitLab 13.8.
The **Analytics > CI/CD Analytics** page shows information about the deployment frequency to the
`production` environment. The environment **must** be named `production` for its deployment
information to appear on the graphs.
![Deployment frequency](img/deployment_frequency_chart_v13_8.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -33,7 +33,7 @@ The following analytics features are available at the group level:
The following analytics features are available at the project level: The following analytics features are available at the project level:
- [CI/CD](../../ci/pipelines/index.md#pipeline-success-and-duration-charts). **(STARTER)** - [CI/CD](ci_cd_analytics.md). **(CORE)**
- [Code Review](code_review_analytics.md). **(STARTER)** - [Code Review](code_review_analytics.md). **(STARTER)**
- [Insights](../project/insights/index.md). **(ULTIMATE)** - [Insights](../project/insights/index.md). **(ULTIMATE)**
- [Issue](../group/issues_analytics/index.md). **(PREMIUM)** - [Issue](../group/issues_analytics/index.md). **(PREMIUM)**

View File

@ -383,7 +383,7 @@ mutation deleteState {
} }
``` ```
You can obtain the <global_id_for_the_state> by querying the list of states. For example: You can obtain the `<global_id_for_the_state>` by querying the list of states. For example:
```shell ```shell
query ProjectTerraformStates { query ProjectTerraformStates {

View File

@ -15,23 +15,39 @@ module Gitlab
# schedules a job which parses peek profile data and adds them # schedules a job which parses peek profile data and adds them
# to a structured log # to a structured log
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def enqueue_stats_job(request_id) def enqueue_stats_job(request_id)
return unless gather_stats? return unless gather_stats?
@client.sadd(GitlabPerformanceBarStatsWorker::STATS_KEY, request_id) # rubocop:disable Gitlab/ModuleWithInstanceVariables @client.sadd(GitlabPerformanceBarStatsWorker::STATS_KEY, request_id)
return unless uuid = Gitlab::ExclusiveLease.new( return unless uuid = Gitlab::ExclusiveLease.new(
GitlabPerformanceBarStatsWorker::LEASE_KEY, GitlabPerformanceBarStatsWorker::LEASE_KEY,
timeout: GitlabPerformanceBarStatsWorker::LEASE_TIMEOUT timeout: GitlabPerformanceBarStatsWorker::LEASE_TIMEOUT
).try_obtain ).try_obtain
GitlabPerformanceBarStatsWorker.perform_in(GitlabPerformanceBarStatsWorker::WORKER_DELAY, uuid) # stats key should be periodically processed and deleted by
# GitlabPerformanceBarStatsWorker but if it doesn't happen for
# some reason, we set expiration for the stats key to avoid
# keeping millions of request ids which would be already expired
# anyway
# rubocop:disable Gitlab/ModuleWithInstanceVariables
@client.expire(
GitlabPerformanceBarStatsWorker::STATS_KEY,
GitlabPerformanceBarStatsWorker::STATS_KEY_EXPIRE
)
GitlabPerformanceBarStatsWorker.perform_in(
GitlabPerformanceBarStatsWorker::WORKER_DELAY,
uuid
)
end end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
def gather_stats? def gather_stats?
return unless Feature.enabled?(:performance_bar_stats) return unless Feature.enabled?(:performance_bar_stats)
Gitlab.com? || !Rails.env.production? Gitlab.com? || Gitlab.staging? || !Rails.env.production?
end end
end end
end end

View File

@ -11,7 +11,7 @@ class GitlabDanger
karma karma
database database
commit_messages commit_messages
product_analytics product_intelligence
utility_css utility_css
pajamas pajamas
pipeline pipeline

View File

@ -19609,12 +19609,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule" msgid "OnCallSchedules|Failed to edit schedule"
msgstr "" msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
msgid "OnCallSchedules|On-call schedule" msgid "OnCallSchedules|On-call schedule"
msgstr "" msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}" msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr "" msgstr ""
msgid "OnCallSchedules|Restrict to time intervals"
msgstr ""
msgid "OnCallSchedules|Rotation length" msgid "OnCallSchedules|Rotation length"
msgstr "" msgstr ""

View File

@ -31,6 +31,7 @@ RSpec.describe Gitlab::PerformanceBar::RedisAdapterWhenPeekEnabled do
expect_to_obtain_exclusive_lease(GitlabPerformanceBarStatsWorker::LEASE_KEY, uuid) expect_to_obtain_exclusive_lease(GitlabPerformanceBarStatsWorker::LEASE_KEY, uuid)
expect(GitlabPerformanceBarStatsWorker).to receive(:perform_in).with(GitlabPerformanceBarStatsWorker::WORKER_DELAY, uuid) expect(GitlabPerformanceBarStatsWorker).to receive(:perform_in).with(GitlabPerformanceBarStatsWorker::WORKER_DELAY, uuid)
expect(client).to receive(:sadd).with(GitlabPerformanceBarStatsWorker::STATS_KEY, uuid) expect(client).to receive(:sadd).with(GitlabPerformanceBarStatsWorker::STATS_KEY, uuid)
expect(client).to receive(:expire).with(GitlabPerformanceBarStatsWorker::STATS_KEY, GitlabPerformanceBarStatsWorker::STATS_KEY_EXPIRE)
peek_adapter.new(client).save('foo') peek_adapter.new(client).save('foo')
end end

View File

@ -145,7 +145,7 @@ RSpec.shared_examples 'Debian Distribution' do |factory, container, can_freeze|
subject { described_class.with_container(distribution_with_suite.container) } subject { described_class.with_container(distribution_with_suite.container) }
it 'does not return other distributions' do it 'does not return other distributions' do
expect(subject.to_a).to eq([distribution_with_suite, distribution, distribution_with_same_container]) expect(subject).to match_array([distribution_with_suite, distribution, distribution_with_same_container])
end end
end end
@ -153,7 +153,7 @@ RSpec.shared_examples 'Debian Distribution' do |factory, container, can_freeze|
subject { described_class.with_codename(distribution_with_suite.codename) } subject { described_class.with_codename(distribution_with_suite.codename) }
it 'does not return other distributions' do it 'does not return other distributions' do
expect(subject.to_a).to eq([distribution_with_suite, distribution_with_same_codename]) expect(subject).to match_array([distribution_with_suite, distribution_with_same_codename])
end end
end end
@ -161,7 +161,7 @@ RSpec.shared_examples 'Debian Distribution' do |factory, container, can_freeze|
subject { described_class.with_suite(distribution_with_suite.suite) } subject { described_class.with_suite(distribution_with_suite.suite) }
it 'does not return other distributions' do it 'does not return other distributions' do
expect(subject.to_a).to eq([distribution_with_suite, distribution_with_same_suite]) expect(subject).to match_array([distribution_with_suite, distribution_with_same_suite])
end end
end end
end end

View File

@ -12,7 +12,7 @@ RSpec.describe GitlabPerformanceBarStatsWorker do
let(:uuid) { 1 } let(:uuid) { 1 }
before do before do
expect(Gitlab::Redis::SharedState).to receive(:with).and_yield(redis) expect(Gitlab::Redis::Cache).to receive(:with).and_yield(redis)
expect_to_cancel_exclusive_lease(GitlabPerformanceBarStatsWorker::LEASE_KEY, uuid) expect_to_cancel_exclusive_lease(GitlabPerformanceBarStatsWorker::LEASE_KEY, uuid)
end end