Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-02-28 15:13:55 +00:00
parent 4eac7e06bd
commit 8188ca655a
47 changed files with 595 additions and 569 deletions

View File

@ -239,6 +239,10 @@ Rails/FindBy:
- 'spec/**/*.rb'
- 'ee/spec/**/*.rb'
Rails/IndexBy:
Exclude:
- 'tooling/danger/**/*.rb'
# This is currently exiting with a rubocop exception error and should be
# resolved hopefully a future update
# An error occurred while Rails/UniqueValidationWithoutIndex cop was inspecting
@ -610,7 +614,6 @@ Rails/TimeZone:
- 'spec/features/**/*'
- 'ee/spec/features/**/*'
# WIP: See https://gitlab.com/gitlab-org/gitlab/-/issues/220040
Rails/SaveBang:
Enabled: true
AllowImplicitReturn: false

View File

@ -458,24 +458,6 @@ Rails/HasManyOrHasOneDependent:
Rails/HelperInstanceVariable:
Enabled: false
# Offense count: 17
# Cop supports --auto-correct.
Rails/IndexBy:
Exclude:
- 'app/graphql/types/design_management/design_fields.rb'
- 'app/models/ci/pipeline.rb'
- 'app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb'
- 'ee/app/services/projects/update_mirror_service.rb'
- 'ee/app/services/security/store_report_service.rb'
- 'ee/lib/ee/gitlab/auth/ldap/sync/group.rb'
- 'ee/lib/ee/gitlab/background_migration/backfill_version_data_from_gitaly.rb'
- 'ee/lib/gitlab/analytics/type_of_work/tasks_by_type.rb'
- 'ee/lib/gitlab/elastic/document_reference.rb'
- 'ee/lib/gitlab/group_plans_preloader.rb'
- 'lib/gitlab/database/count/reltuples_count_strategy.rb'
- 'lib/gitlab/language_detection.rb'
- 'tooling/danger/sidekiq_queues.rb'
# Offense count: 47
# Cop supports --auto-correct.
Rails/IndexWith:

View File

@ -1,16 +1,6 @@
---
GraphQL/OrderedFields:
Exclude:
- app/graphql/types/board_list_type.rb
- app/graphql/types/ci/analytics_type.rb
- app/graphql/types/ci/ci_cd_setting_type.rb
- app/graphql/types/ci/config/group_type.rb
- app/graphql/types/ci/config/job_type.rb
- app/graphql/types/ci/config/stage_type.rb
- app/graphql/types/ci/detailed_status_type.rb
- app/graphql/types/ci/group_type.rb
- app/graphql/types/ci/job_type.rb
- app/graphql/types/ci/runner_architecture_type.rb
- app/graphql/types/ci/runner_platform_type.rb
- app/graphql/types/ci/runner_type.rb
- app/graphql/types/ci/stage_type.rb
@ -48,14 +38,6 @@ GraphQL/OrderedFields:
- app/graphql/types/notes/diff_position_type.rb
- app/graphql/types/notes/discussion_type.rb
- app/graphql/types/notes/note_type.rb
- app/graphql/types/packages/composer/json_type.rb
- app/graphql/types/packages/composer/metadatum_type.rb
- app/graphql/types/packages/conan/file_metadatum_type.rb
- app/graphql/types/packages/conan/metadatum_type.rb
- app/graphql/types/packages/helm/dependency_type.rb
- app/graphql/types/packages/helm/maintainer_type.rb
- app/graphql/types/packages/helm/metadata_type.rb
- app/graphql/types/packages/maven/metadatum_type.rb
- app/graphql/types/packages/nuget/metadatum_type.rb
- app/graphql/types/packages/package_dependency_link_type.rb
- app/graphql/types/packages/package_file_type.rb

View File

@ -63,6 +63,9 @@ export default {
isEmpty() {
return this.blob.rawSize === 0;
},
blobSwitcherDocIcon() {
return this.blob.richViewer?.fileType === 'csv' ? 'table' : 'document';
},
},
watch: {
viewer(newVal, oldVal) {
@ -90,7 +93,7 @@ export default {
</div>
<div class="gl-sm-display-flex file-actions">
<viewer-switcher v-if="showViewerSwitcher" v-model="viewer" />
<viewer-switcher v-if="showViewerSwitcher" v-model="viewer" :doc-icon="blobSwitcherDocIcon" />
<slot name="actions"></slot>

View File

@ -21,6 +21,11 @@ export default {
default: SIMPLE_BLOB_VIEWER,
required: false,
},
docIcon: {
type: String,
default: 'document',
required: false,
},
},
computed: {
isSimpleViewer() {
@ -62,7 +67,7 @@ export default {
:aria-label="$options.RICH_BLOB_VIEWER_TITLE"
:title="$options.RICH_BLOB_VIEWER_TITLE"
:selected="isRichViewer"
icon="document"
:icon="docIcon"
category="primary"
variant="default"
class="js-blob-viewer-switch-btn"

View File

@ -14,6 +14,11 @@ export default {
type: String,
required: true,
},
remoteFile: {
type: Boolean,
required: false,
default: false,
},
},
data() {
return {
@ -23,14 +28,29 @@ export default {
};
},
mounted() {
const parsed = Papa.parse(this.csv, { skipEmptyLines: true });
this.items = parsed.data;
if (parsed.errors.length) {
this.papaParseErrors = parsed.errors;
if (!this.remoteFile) {
const parsed = Papa.parse(this.csv, { skipEmptyLines: true });
this.handleParsedData(parsed);
} else {
Papa.parse(this.csv, {
download: true,
skipEmptyLines: true,
complete: (parsed) => {
this.handleParsedData(parsed);
},
});
}
},
methods: {
handleParsedData(parsed) {
this.items = parsed.data;
this.loading = false;
if (parsed.errors.length) {
this.papaParseErrors = parsed.errors;
}
this.loading = false;
},
},
};
</script>

View File

@ -1,5 +1,5 @@
<script>
import { GlLink, GlTooltip, GlResizeObserverDirective, GlIcon } from '@gitlab/ui';
import { GlLink, GlTooltip, GlIcon } from '@gitlab/ui';
import { GlAreaChart, GlLineChart, GlChartSeriesLabel } from '@gitlab/ui/dist/charts';
import { isEmpty, omit, throttle } from 'lodash';
import { makeDataSeries } from '~/helpers/monitor_helper';
@ -28,9 +28,6 @@ export default {
GlLink,
GlIcon,
},
directives: {
GlResizeObserverDirective,
},
inheritAttrs: false,
props: {
graphData: {
@ -366,64 +363,58 @@ export default {
eChart.off('datazoom');
eChart.on('datazoom', this.throttledDatazoom);
},
onResize() {
if (!this.$refs.chart) return;
const { width } = this.$refs.chart.$el.getBoundingClientRect();
this.width = width;
},
},
};
</script>
<template>
<div v-gl-resize-observer-directive="onResize">
<component
:is="glChartComponent"
ref="chart"
v-bind="$attrs"
:group-id="groupId"
:data="chartData"
:option="chartOptions"
:format-tooltip-text="formatTooltipText"
:format-annotations-tooltip-text="formatAnnotationsTooltipText"
:width="width"
:height="height"
:legend-layout="legendLayout"
:legend-average-text="legendAverageText"
:legend-current-text="legendCurrentText"
:legend-max-text="legendMaxText"
:legend-min-text="legendMinText"
@created="onChartCreated"
@updated="onChartUpdated"
>
<template #tooltip-title>
<template v-if="tooltip.type === 'deployments'">
{{ __('Deployed') }}
</template>
<div v-else class="text-nowrap">
{{ tooltip.title }}
</div>
<component
:is="glChartComponent"
ref="chart"
v-bind="$attrs"
:responsive="true"
:group-id="groupId"
:data="chartData"
:option="chartOptions"
:format-tooltip-text="formatTooltipText"
:format-annotations-tooltip-text="formatAnnotationsTooltipText"
:width="width"
:height="height"
:legend-layout="legendLayout"
:legend-average-text="legendAverageText"
:legend-current-text="legendCurrentText"
:legend-max-text="legendMaxText"
:legend-min-text="legendMinText"
@created="onChartCreated"
@updated="onChartUpdated"
>
<template #tooltip-title>
<template v-if="tooltip.type === 'deployments'">
{{ __('Deployed') }}
</template>
<template #tooltip-content>
<div v-if="tooltip.type === 'deployments'" class="d-flex align-items-center">
<gl-icon name="commit" class="mr-2" />
<gl-link :href="tooltip.commitUrl">{{ tooltip.sha }}</gl-link>
</div>
<template v-else>
<div
v-for="(content, key) in tooltip.content"
:key="key"
class="d-flex justify-content-between"
>
<gl-chart-series-label :color="isMultiSeries ? content.color : ''">
{{ content.name }}
</gl-chart-series-label>
<div class="gl-ml-7">
{{ content.value }}
</div>
<div v-else class="text-nowrap">
{{ tooltip.title }}
</div>
</template>
<template #tooltip-content>
<div v-if="tooltip.type === 'deployments'" class="d-flex align-items-center">
<gl-icon name="commit" class="mr-2" />
<gl-link :href="tooltip.commitUrl">{{ tooltip.sha }}</gl-link>
</div>
<template v-else>
<div
v-for="(content, key) in tooltip.content"
:key="key"
class="d-flex justify-content-between"
>
<gl-chart-series-label :color="isMultiSeries ? content.color : ''">
{{ content.name }}
</gl-chart-series-label>
<div class="gl-ml-7">
{{ content.value }}
</div>
</template>
</div>
</template>
</component>
</div>
</template>
</component>
</template>

View File

@ -0,0 +1,26 @@
<script>
import CsvViewer from '~/blob/csv/csv_viewer.vue';
export default {
components: {
CsvViewer,
},
props: {
blob: {
type: Object,
required: true,
},
},
data() {
return {
url: this.blob.rawPath,
};
},
};
</script>
<template>
<div>
<csv-viewer :csv="url" remote-file data-testid="csv" />
</div>
</template>

View File

@ -1,4 +1,5 @@
const viewers = {
csv: () => import('./csv_viewer.vue'),
download: () => import('./download_viewer.vue'),
image: () => import('./image_viewer.vue'),
video: () => import('./video_viewer.vue'),

View File

@ -7,6 +7,7 @@
:invalid-feedback="__('Please enter a valid hex (#RRGGBB or #RGB) color value')"
:label="__('Background color')"
:value="#FF0000"
:suggestedColors="{ '#ff0000': 'Red', '#808080': 'Gray' }",
state="isValidColor"
/>
*/
@ -48,6 +49,11 @@ export default {
required: false,
default: null,
},
suggestedColors: {
type: Object,
required: false,
default: () => gon.suggested_label_colors,
},
},
computed: {
description() {
@ -55,9 +61,6 @@ export default {
? this.$options.i18n.fullDescription
: this.$options.i18n.shortDescription;
},
suggestedColors() {
return gon.suggested_label_colors;
},
previewColor() {
if (this.state) {
return { backgroundColor: this.value };

View File

@ -14,18 +14,18 @@ module Types
null: false,
description: 'ID (global ID) of the list.'
field :title, GraphQL::Types::String, null: false,
description: 'Title of the list.'
field :list_type, GraphQL::Types::String, null: false,
description: 'Type of the list.'
field :position, GraphQL::Types::Int, null: true,
description: 'Position of list within the board.'
field :label, Types::LabelType, null: true,
description: 'Label of the list.'
field :collapsed, GraphQL::Types::Boolean, null: true,
description: 'Indicates if the list is collapsed for this user.'
field :issues_count, GraphQL::Types::Int, null: true,
description: 'Count of issues in the list.'
field :label, Types::LabelType, null: true,
description: 'Label of the list.'
field :list_type, GraphQL::Types::String, null: false,
description: 'Type of the list.'
field :position, GraphQL::Types::Int, null: true,
description: 'Position of list within the board.'
field :title, GraphQL::Types::String, null: false,
description: 'Title of the list.'
field :issues, ::Types::IssueType.connection_type, null: true,
description: 'Board issues.',

View File

@ -6,28 +6,28 @@ module Types
class AnalyticsType < BaseObject
graphql_name 'PipelineAnalytics'
field :week_pipelines_totals, [GraphQL::Types::Int], null: true,
description: 'Total weekly pipeline count.'
field :week_pipelines_successful, [GraphQL::Types::Int], null: true,
description: 'Total weekly successful pipeline count.'
field :week_pipelines_labels, [GraphQL::Types::String], null: true,
description: 'Labels for the weekly pipeline count.'
field :month_pipelines_totals, [GraphQL::Types::Int], null: true,
description: 'Total monthly pipeline count.'
field :month_pipelines_successful, [GraphQL::Types::Int], null: true,
description: 'Total monthly successful pipeline count.'
field :month_pipelines_labels, [GraphQL::Types::String], null: true,
description: 'Labels for the monthly pipeline count.'
field :year_pipelines_totals, [GraphQL::Types::Int], null: true,
description: 'Total yearly pipeline count.'
field :year_pipelines_successful, [GraphQL::Types::Int], null: true,
description: 'Total yearly successful pipeline count.'
field :year_pipelines_labels, [GraphQL::Types::String], null: true,
description: 'Labels for the yearly pipeline count.'
field :pipeline_times_values, [GraphQL::Types::Int], null: true,
description: 'Pipeline times.'
field :month_pipelines_successful, [GraphQL::Types::Int], null: true,
description: 'Total monthly successful pipeline count.'
field :month_pipelines_totals, [GraphQL::Types::Int], null: true,
description: 'Total monthly pipeline count.'
field :pipeline_times_labels, [GraphQL::Types::String], null: true,
description: 'Pipeline times labels.'
field :pipeline_times_values, [GraphQL::Types::Int], null: true,
description: 'Pipeline times.'
field :week_pipelines_labels, [GraphQL::Types::String], null: true,
description: 'Labels for the weekly pipeline count.'
field :week_pipelines_successful, [GraphQL::Types::Int], null: true,
description: 'Total weekly successful pipeline count.'
field :week_pipelines_totals, [GraphQL::Types::Int], null: true,
description: 'Total weekly pipeline count.'
field :year_pipelines_labels, [GraphQL::Types::String], null: true,
description: 'Labels for the yearly pipeline count.'
field :year_pipelines_successful, [GraphQL::Types::Int], null: true,
description: 'Total yearly successful pipeline count.'
field :year_pipelines_totals, [GraphQL::Types::Int], null: true,
description: 'Total yearly pipeline count.'
end
end
end

View File

@ -7,18 +7,18 @@ module Types
authorize :admin_project
field :job_token_scope_enabled, GraphQL::Types::Boolean, null: true,
description: 'Indicates CI job tokens generated in this project have restricted access to resources.',
method: :job_token_scope_enabled?
field :keep_latest_artifact, GraphQL::Types::Boolean, null: true,
description: 'Whether to keep the latest builds artifacts.',
method: :keep_latest_artifacts_available?
field :merge_pipelines_enabled, GraphQL::Types::Boolean, null: true,
description: 'Whether merge pipelines are enabled.',
method: :merge_pipelines_enabled?
field :merge_trains_enabled, GraphQL::Types::Boolean, null: true,
description: 'Whether merge trains are enabled.',
method: :merge_trains_enabled?
field :keep_latest_artifact, GraphQL::Types::Boolean, null: true,
description: 'Whether to keep the latest builds artifacts.',
method: :keep_latest_artifacts_available?
field :job_token_scope_enabled, GraphQL::Types::Boolean, null: true,
description: 'Indicates CI job tokens generated in this project have restricted access to resources.',
method: :job_token_scope_enabled?
field :project, Types::ProjectType, null: true,
description: 'Project the CI/CD settings belong to.'
end

View File

@ -7,10 +7,10 @@ module Types
class GroupType < BaseObject
graphql_name 'CiConfigGroup'
field :name, GraphQL::Types::String, null: true,
description: 'Name of the job group.'
field :jobs, Types::Ci::Config::JobType.connection_type, null: true,
description: 'Jobs in group.'
field :name, GraphQL::Types::String, null: true,
description: 'Name of the job group.'
field :size, GraphQL::Types::Int, null: true,
description: 'Size of the job group.'
end

View File

@ -7,33 +7,33 @@ module Types
class JobType < BaseObject
graphql_name 'CiConfigJob'
field :name, GraphQL::Types::String, null: true,
description: 'Name of the job.'
field :group_name, GraphQL::Types::String, null: true,
description: 'Name of the job group.'
field :stage, GraphQL::Types::String, null: true,
description: 'Name of the job stage.'
field :needs, Types::Ci::Config::NeedType.connection_type, null: true,
description: 'Builds that must complete before the jobs run.'
field :after_script, [GraphQL::Types::String], null: true,
description: 'Override a set of commands that are executed after the job.'
field :allow_failure, GraphQL::Types::Boolean, null: true,
description: 'Allow job to fail.'
field :before_script, [GraphQL::Types::String], null: true,
description: 'Override a set of commands that are executed before the job.'
field :script, [GraphQL::Types::String], null: true,
description: 'Shell script that is executed by a runner.'
field :after_script, [GraphQL::Types::String], null: true,
description: 'Override a set of commands that are executed after the job.'
field :when, GraphQL::Types::String, null: true,
description: 'When to run the job.',
resolver_method: :restrict_when_to_run_jobs
field :environment, GraphQL::Types::String, null: true,
description: 'Name of an environment to which the job deploys.'
field :except, Types::Ci::Config::JobRestrictionType, null: true,
description: 'Limit when jobs are not created.'
field :group_name, GraphQL::Types::String, null: true,
description: 'Name of the job group.'
field :name, GraphQL::Types::String, null: true,
description: 'Name of the job.'
field :needs, Types::Ci::Config::NeedType.connection_type, null: true,
description: 'Builds that must complete before the jobs run.'
field :only, Types::Ci::Config::JobRestrictionType, null: true,
description: 'Jobs are created when these conditions do not apply.'
field :script, [GraphQL::Types::String], null: true,
description: 'Shell script that is executed by a runner.'
field :stage, GraphQL::Types::String, null: true,
description: 'Name of the job stage.'
field :tags, [GraphQL::Types::String], null: true,
description: 'List of tags that are used to select a runner.'
field :when, GraphQL::Types::String, null: true,
description: 'When to run the job.',
resolver_method: :restrict_when_to_run_jobs
def restrict_when_to_run_jobs
object[:when]

View File

@ -7,10 +7,10 @@ module Types
class StageType < BaseObject
graphql_name 'CiConfigStage'
field :name, GraphQL::Types::String, null: true,
description: 'Name of the stage.'
field :groups, Types::Ci::Config::GroupType.connection_type, null: true,
description: 'Groups of jobs for the stage.'
field :name, GraphQL::Types::String, null: true,
description: 'Name of the stage.'
end
end
end

View File

@ -6,20 +6,23 @@ module Types
class DetailedStatusType < BaseObject
graphql_name 'DetailedStatus'
field :id, GraphQL::Types::String, null: false,
description: 'ID for a detailed status.',
extras: [:parent]
field :group, GraphQL::Types::String, null: true,
description: 'Group of the status.'
field :icon, GraphQL::Types::String, null: true,
description: 'Icon of the status.'
field :favicon, GraphQL::Types::String, null: true,
description: 'Favicon of the status.'
field :action, Types::Ci::StatusActionType, null: true,
calls_gitaly: true,
description: 'Action information for the status. This includes method, button title, icon, path, and title.'
field :details_path, GraphQL::Types::String, null: true,
description: 'Path of the details for the status.'
field :favicon, GraphQL::Types::String, null: true,
description: 'Favicon of the status.'
field :group, GraphQL::Types::String, null: true,
description: 'Group of the status.'
field :has_details, GraphQL::Types::Boolean, null: true,
description: 'Indicates if the status has further details.',
method: :has_details?
field :icon, GraphQL::Types::String, null: true,
description: 'Icon of the status.'
field :id, GraphQL::Types::String, null: false,
description: 'ID for a detailed status.',
extras: [:parent]
field :label, GraphQL::Types::String, null: true,
calls_gitaly: true,
description: 'Label of the status.'
@ -28,9 +31,6 @@ module Types
field :tooltip, GraphQL::Types::String, null: true,
description: 'Tooltip associated with the status.',
method: :status_tooltip
field :action, Types::Ci::StatusActionType, null: true,
calls_gitaly: true,
description: 'Action information for the status. This includes method, button title, icon, path, and title.'
def id(parent:)
"#{object.id}-#{parent.object.object.id}"

View File

@ -6,16 +6,16 @@ module Types
class GroupType < BaseObject
graphql_name 'CiGroup'
field :detailed_status, Types::Ci::DetailedStatusType, null: true,
description: 'Detailed status of the group.'
field :id, GraphQL::Types::String, null: false,
description: 'ID for a group.'
field :jobs, Ci::JobType.connection_type, null: true,
description: 'Jobs in group.'
field :name, GraphQL::Types::String, null: true,
description: 'Name of the job group.'
field :size, GraphQL::Types::Int, null: true,
description: 'Size of the group.'
field :jobs, Ci::JobType.connection_type, null: true,
description: 'Jobs in group.'
field :detailed_status, Types::Ci::DetailedStatusType, null: true,
description: 'Detailed status of the group.'
def detailed_status
object.detailed_status(context[:current_user])

View File

@ -11,38 +11,38 @@ module Types
expose_permissions Types::PermissionTypes::Ci::Job
field :id, ::Types::GlobalIDType[::CommitStatus].as('JobID'), null: true,
description: 'ID of the job.'
field :pipeline, Types::Ci::PipelineType, null: true,
description: 'Pipeline the job belongs to.'
field :name, GraphQL::Types::String, null: true,
description: 'Name of the job.'
field :needs, BuildNeedType.connection_type, null: true,
description: 'References to builds that must complete before the jobs run.'
field :status,
type: ::Types::Ci::JobStatusEnum,
null: true,
description: "Status of the job."
field :stage, Types::Ci::StageType, null: true,
description: 'Stage of the job.'
field :allow_failure, ::GraphQL::Types::Boolean, null: false,
description: 'Whether the job is allowed to fail.'
field :duration, GraphQL::Types::Int, null: true,
description: 'Duration of the job in seconds.'
field :id, ::Types::GlobalIDType[::CommitStatus].as('JobID'), null: true,
description: 'ID of the job.'
field :name, GraphQL::Types::String, null: true,
description: 'Name of the job.'
field :needs, BuildNeedType.connection_type, null: true,
description: 'References to builds that must complete before the jobs run.'
field :pipeline, Types::Ci::PipelineType, null: true,
description: 'Pipeline the job belongs to.'
field :stage, Types::Ci::StageType, null: true,
description: 'Stage of the job.'
field :status,
type: ::Types::Ci::JobStatusEnum,
null: true,
description: "Status of the job."
field :tags, [GraphQL::Types::String], null: true,
description: 'Tags for the current job.'
# Life-cycle timestamps:
field :created_at, Types::TimeType, null: false,
description: "When the job was created."
field :queued_at, Types::TimeType, null: true,
description: 'When the job was enqueued and marked as pending.'
field :started_at, Types::TimeType, null: true,
description: 'When the job was started.'
field :finished_at, Types::TimeType, null: true,
description: 'When a job has finished running.'
field :queued_at, Types::TimeType, null: true,
description: 'When the job was enqueued and marked as pending.'
field :scheduled_at, Types::TimeType, null: true,
description: 'Schedule for the build.'
field :started_at, Types::TimeType, null: true,
description: 'When the job was started.'
# Life-cycle durations:
field :queued_duration,
@ -50,40 +50,40 @@ module Types
null: true,
description: 'How long the job was enqueued before starting.'
field :downstream_pipeline, Types::Ci::PipelineType, null: true,
description: 'Downstream pipeline for a bridge.'
field :previous_stage_jobs_or_needs, Types::Ci::JobNeedUnion.connection_type, null: true,
description: 'Jobs that must complete before the job runs. Returns `BuildNeed`, which is the needed jobs if the job uses the `needs` keyword, or the previous stage jobs otherwise.'
field :detailed_status, Types::Ci::DetailedStatusType, null: true,
description: 'Detailed status of the job.'
field :artifacts, Types::Ci::JobArtifactType.connection_type, null: true,
description: 'Artifacts generated by the job.'
field :short_sha, type: GraphQL::Types::String, null: false,
description: 'Short SHA1 ID of the commit.'
field :scheduling_type, GraphQL::Types::String, null: true,
description: 'Type of job scheduling. Value is `dag` if the job uses the `needs` keyword, and `stage` otherwise.'
field :commit_path, GraphQL::Types::String, null: true,
description: 'Path to the commit that triggered the job.'
field :ref_name, GraphQL::Types::String, null: true,
description: 'Ref name of the job.'
field :ref_path, GraphQL::Types::String, null: true,
description: 'Path to the ref.'
field :playable, GraphQL::Types::Boolean, null: false, method: :playable?,
description: 'Indicates the job can be played.'
field :retryable, GraphQL::Types::Boolean, null: false, method: :retryable?,
description: 'Indicates the job can be retried.'
field :cancelable, GraphQL::Types::Boolean, null: false, method: :cancelable?,
description: 'Indicates the job can be canceled.'
field :active, GraphQL::Types::Boolean, null: false, method: :active?,
description: 'Indicates the job is active.'
field :stuck, GraphQL::Types::Boolean, null: false, method: :stuck?,
description: 'Indicates the job is stuck.'
field :artifacts, Types::Ci::JobArtifactType.connection_type, null: true,
description: 'Artifacts generated by the job.'
field :cancelable, GraphQL::Types::Boolean, null: false, method: :cancelable?,
description: 'Indicates the job can be canceled.'
field :commit_path, GraphQL::Types::String, null: true,
description: 'Path to the commit that triggered the job.'
field :coverage, GraphQL::Types::Float, null: true,
description: 'Coverage level of the job.'
field :created_by_tag, GraphQL::Types::Boolean, null: false,
description: 'Whether the job was created by a tag.'
field :detailed_status, Types::Ci::DetailedStatusType, null: true,
description: 'Detailed status of the job.'
field :downstream_pipeline, Types::Ci::PipelineType, null: true,
description: 'Downstream pipeline for a bridge.'
field :manual_job, GraphQL::Types::Boolean, null: true,
description: 'Whether the job has a manual action.'
field :playable, GraphQL::Types::Boolean, null: false, method: :playable?,
description: 'Indicates the job can be played.'
field :previous_stage_jobs_or_needs, Types::Ci::JobNeedUnion.connection_type, null: true,
description: 'Jobs that must complete before the job runs. Returns `BuildNeed`, which is the needed jobs if the job uses the `needs` keyword, or the previous stage jobs otherwise.'
field :ref_name, GraphQL::Types::String, null: true,
description: 'Ref name of the job.'
field :ref_path, GraphQL::Types::String, null: true,
description: 'Path to the ref.'
field :retryable, GraphQL::Types::Boolean, null: false, method: :retryable?,
description: 'Indicates the job can be retried.'
field :scheduling_type, GraphQL::Types::String, null: true,
description: 'Type of job scheduling. Value is `dag` if the job uses the `needs` keyword, and `stage` otherwise.'
field :short_sha, type: GraphQL::Types::String, null: false,
description: 'Short SHA1 ID of the commit.'
field :stuck, GraphQL::Types::Boolean, null: false, method: :stuck?,
description: 'Indicates the job is stuck.'
field :triggered, GraphQL::Types::Boolean, null: true,
description: 'Whether the job was triggered.'

View File

@ -6,10 +6,10 @@ module Types
class RunnerArchitectureType < BaseObject
graphql_name 'RunnerArchitecture'
field :name, GraphQL::Types::String, null: false,
description: 'Name of the runner platform architecture.'
field :download_location, GraphQL::Types::String, null: false,
description: 'Download location for the runner for the platform architecture.'
field :name, GraphQL::Types::String, null: false,
description: 'Name of the runner platform architecture.'
end
end
end

View File

@ -62,7 +62,7 @@ module Types
def cached_actions_for_version(version)
Gitlab::SafeRequestStore.fetch(['DesignFields', 'actions_for_version', version.id]) do
version.actions.to_h { |dv| [dv.design_id, dv] }
version.actions.index_by(&:design_id)
end
end

View File

@ -8,9 +8,9 @@ module Types
graphql_name 'PackageComposerJsonType'
description 'Represents a composer JSON file'
field :license, GraphQL::Types::String, null: true, description: 'License set in the Composer JSON file.'
field :name, GraphQL::Types::String, null: true, description: 'Name set in the Composer JSON file.'
field :type, GraphQL::Types::String, null: true, description: 'Type set in the Composer JSON file.'
field :license, GraphQL::Types::String, null: true, description: 'License set in the Composer JSON file.'
field :version, GraphQL::Types::String, null: true, description: 'Version set in the Composer JSON file.'
end
end

View File

@ -9,8 +9,8 @@ module Types
authorize :read_package
field :target_sha, GraphQL::Types::String, null: false, description: 'Target SHA of the package.'
field :composer_json, Types::Packages::Composer::JsonType, null: false, description: 'Data of the Composer JSON file.'
field :target_sha, GraphQL::Types::String, null: false, description: 'Target SHA of the package.'
end
end
end

View File

@ -11,11 +11,11 @@ module Types
authorize :read_package
field :id, ::Types::GlobalIDType[::Packages::Conan::FileMetadatum], null: false, description: 'ID of the metadatum.'
field :recipe_revision, GraphQL::Types::String, null: false, description: 'Revision of the Conan recipe.'
field :package_revision, GraphQL::Types::String, null: true, description: 'Revision of the package.'
field :conan_package_reference, GraphQL::Types::String, null: true, description: 'Reference of the Conan package.'
field :conan_file_type, ::Types::Packages::Conan::MetadatumFileTypeEnum, null: false, description: 'Type of the Conan file.'
field :conan_package_reference, GraphQL::Types::String, null: true, description: 'Reference of the Conan package.'
field :id, ::Types::GlobalIDType[::Packages::Conan::FileMetadatum], null: false, description: 'ID of the metadatum.'
field :package_revision, GraphQL::Types::String, null: true, description: 'Revision of the package.'
field :recipe_revision, GraphQL::Types::String, null: false, description: 'Revision of the Conan recipe.'
end
end
end

View File

@ -9,13 +9,13 @@ module Types
authorize :read_package
field :id, ::Types::GlobalIDType[::Packages::Conan::Metadatum], null: false, description: 'ID of the metadatum.'
field :created_at, Types::TimeType, null: false, description: 'Date of creation.'
field :updated_at, Types::TimeType, null: false, description: 'Date of most recent update.'
field :package_username, GraphQL::Types::String, null: false, description: 'Username of the Conan package.'
field :id, ::Types::GlobalIDType[::Packages::Conan::Metadatum], null: false, description: 'ID of the metadatum.'
field :package_channel, GraphQL::Types::String, null: false, description: 'Channel of the Conan package.'
field :package_username, GraphQL::Types::String, null: false, description: 'Username of the Conan package.'
field :recipe, GraphQL::Types::String, null: false, description: 'Recipe of the Conan package.'
field :recipe_path, GraphQL::Types::String, null: false, description: 'Recipe path of the Conan package.'
field :updated_at, Types::TimeType, null: false, description: 'Date of most recent update.'
end
end
end

View File

@ -9,14 +9,14 @@ module Types
description 'Represents a Helm dependency'
# Need to be synced with app/validators/json_schemas/helm_metadata.json#dependencies
field :name, GraphQL::Types::String, null: true, description: 'Name of the dependency.'
field :version, GraphQL::Types::String, null: true, description: 'Version of the dependency.'
field :repository, GraphQL::Types::String, null: true, description: 'Repository of the dependency.'
field :alias, GraphQL::Types::String, null: true, description: 'Alias of the dependency.', resolver_method: :resolve_alias
field :condition, GraphQL::Types::String, null: true, description: 'Condition of the dependency.'
field :tags, [GraphQL::Types::String], null: true, description: 'Tags of the dependency.'
field :enabled, GraphQL::Types::Boolean, null: true, description: 'Indicates the dependency is enabled.'
field :import_values, [GraphQL::Types::JSON], null: true, description: 'Import-values of the dependency.', hash_key: "import-values" # rubocop:disable Graphql/JSONType
field :alias, GraphQL::Types::String, null: true, description: 'Alias of the dependency.', resolver_method: :resolve_alias
field :name, GraphQL::Types::String, null: true, description: 'Name of the dependency.'
field :repository, GraphQL::Types::String, null: true, description: 'Repository of the dependency.'
field :tags, [GraphQL::Types::String], null: true, description: 'Tags of the dependency.'
field :version, GraphQL::Types::String, null: true, description: 'Version of the dependency.'
# field :alias` conflicts with a built-in method
def resolve_alias

View File

@ -9,8 +9,8 @@ module Types
description 'Represents a Helm maintainer'
# Need to be synced with app/validators/json_schemas/helm_metadata.json#maintainers
field :name, GraphQL::Types::String, null: true, description: 'Name of the maintainer.'
field :email, GraphQL::Types::String, null: true, description: 'Email of the maintainer.'
field :name, GraphQL::Types::String, null: true, description: 'Name of the maintainer.'
field :url, GraphQL::Types::String, null: true, description: 'URL of the maintainer.'
end
end

View File

@ -9,23 +9,23 @@ module Types
description 'Represents the contents of a Helm Chart.yml file'
# Need to be synced with app/validators/json_schemas/helm_metadata.json
field :name, GraphQL::Types::String, null: false, description: 'Name of the chart.'
field :home, GraphQL::Types::String, null: true, description: 'URL of the home page.'
field :sources, [GraphQL::Types::String], null: true, description: 'URLs of the source code for the chart.'
field :version, GraphQL::Types::String, null: false, description: 'Version of the chart.'
field :description, GraphQL::Types::String, null: true, description: 'Description of the chart.'
field :keywords, [GraphQL::Types::String], null: true, description: 'Keywords for the chart.'
field :maintainers, [Types::Packages::Helm::MaintainerType], null: true, description: 'Maintainers of the chart.'
field :icon, GraphQL::Types::String, null: true, description: 'URL to an SVG or PNG image for the chart.'
field :api_version, GraphQL::Types::String, null: false, description: 'API version of the chart.', hash_key: "apiVersion"
field :condition, GraphQL::Types::String, null: true, description: 'Condition for the chart.'
field :tags, GraphQL::Types::String, null: true, description: 'Tags for the chart.'
field :app_version, GraphQL::Types::String, null: true, description: 'App version of the chart.', hash_key: "appVersion"
field :deprecated, GraphQL::Types::Boolean, null: true, description: 'Indicates if the chart is deprecated.'
field :annotations, GraphQL::Types::JSON, null: true, description: 'Annotations for the chart.' # rubocop:disable Graphql/JSONType
field :kube_version, GraphQL::Types::String, null: true, description: 'Kubernetes versions for the chart.', hash_key: "kubeVersion"
field :api_version, GraphQL::Types::String, null: false, description: 'API version of the chart.', hash_key: "apiVersion"
field :app_version, GraphQL::Types::String, null: true, description: 'App version of the chart.', hash_key: "appVersion"
field :condition, GraphQL::Types::String, null: true, description: 'Condition for the chart.'
field :dependencies, [Types::Packages::Helm::DependencyType], null: true, description: 'Dependencies of the chart.'
field :deprecated, GraphQL::Types::Boolean, null: true, description: 'Indicates if the chart is deprecated.'
field :description, GraphQL::Types::String, null: true, description: 'Description of the chart.'
field :home, GraphQL::Types::String, null: true, description: 'URL of the home page.'
field :icon, GraphQL::Types::String, null: true, description: 'URL to an SVG or PNG image for the chart.'
field :keywords, [GraphQL::Types::String], null: true, description: 'Keywords for the chart.'
field :kube_version, GraphQL::Types::String, null: true, description: 'Kubernetes versions for the chart.', hash_key: "kubeVersion"
field :maintainers, [Types::Packages::Helm::MaintainerType], null: true, description: 'Maintainers of the chart.'
field :name, GraphQL::Types::String, null: false, description: 'Name of the chart.'
field :sources, [GraphQL::Types::String], null: true, description: 'URLs of the source code for the chart.'
field :tags, GraphQL::Types::String, null: true, description: 'Tags for the chart.'
field :type, GraphQL::Types::String, null: true, description: 'Type of the chart.', hash_key: "appVersion"
field :version, GraphQL::Types::String, null: false, description: 'Version of the chart.'
end
end
end

View File

@ -9,13 +9,13 @@ module Types
authorize :read_package
field :id, ::Types::GlobalIDType[::Packages::Maven::Metadatum], null: false, description: 'ID of the metadatum.'
field :created_at, Types::TimeType, null: false, description: 'Date of creation.'
field :updated_at, Types::TimeType, null: false, description: 'Date of most recent update.'
field :path, GraphQL::Types::String, null: false, description: 'Path of the Maven package.'
field :app_group, GraphQL::Types::String, null: false, description: 'App group of the Maven package.'
field :app_version, GraphQL::Types::String, null: true, description: 'App version of the Maven package.'
field :app_name, GraphQL::Types::String, null: false, description: 'App name of the Maven package.'
field :app_version, GraphQL::Types::String, null: true, description: 'App version of the Maven package.'
field :created_at, Types::TimeType, null: false, description: 'Date of creation.'
field :id, ::Types::GlobalIDType[::Packages::Maven::Metadatum], null: false, description: 'ID of the metadatum.'
field :path, GraphQL::Types::String, null: false, description: 'Path of the Maven package.'
field :updated_at, Types::TimeType, null: false, description: 'Date of most recent update.'
end
end
end

View File

@ -421,9 +421,7 @@ module Ci
sql = sql.where(ref: ref) if ref
sql.each_with_object({}) do |pipeline, hash|
hash[pipeline.sha] = pipeline
end
sql.index_by(&:sha)
end
def self.latest_successful_ids_per_project

View File

@ -91,17 +91,13 @@ module Ci
def all_statuses_by_id
strong_memoize(:all_statuses_by_id) do
all_statuses.to_h do |row|
[row[:id], row]
end
all_statuses.index_by { |row| row[:id] }
end
end
def all_statuses_by_name
strong_memoize(:statuses_by_name) do
all_statuses.to_h do |row|
[row[:name], row]
end
all_statuses.index_by { |row| row[:name] }
end
end

View File

@ -74,6 +74,10 @@ module Projects
def remove_snippets
response = ::Snippets::BulkDestroyService.new(current_user, project.snippets).execute
if response.error?
log_error("Snippet deletion failed on #{project.full_path} with the following message: #{response.message}")
end
response.success?
end

View File

@ -624,6 +624,20 @@ otherwise.
If you want a running pipeline to finish even if you push new commits to a merge
request, be sure to start the `dont-interrupt-me` job before pushing.
### Git fetch caching
Because GitLab.com uses the [pack-objects cache](../administration/gitaly/configure_gitaly.md#pack-objects-cache),
concurrent Git fetches of the same pipeline ref are deduplicated on
the Gitaly server (always) and served from cache (when available).
This works well for the following reasons:
- The pack-objects cache is enabled on all Gitaly servers on GitLab.com.
- The CI/CD [Git strategy setting](../ci/pipelines/settings.md#choose-the-default-git-strategy) for `gitlab-org/gitlab` is **Git clone**,
causing all jobs to fetch the same data, which maximizes the cache hit ratio.
- We use [shallow clone](../ci/pipelines/settings.md#limit-the-number-of-changes-fetched-during-clone) to avoid downloading the full Git
history for every job.
### Caching strategy
1. All jobs must only pull caches by default.
@ -657,19 +671,31 @@ request, be sure to start the `dont-interrupt-me` job before pushing.
We limit the artifacts that are saved and retrieved by jobs to the minimum in order to reduce the upload/download time and costs, as well as the artifacts storage.
### Git fetch caching
### Components caching
Because GitLab.com uses the [pack-objects cache](../administration/gitaly/configure_gitaly.md#pack-objects-cache),
concurrent Git fetches of the same pipeline ref are deduplicated on
the Gitaly server (always) and served from cache (when available).
Some external components (currently only GitLab Workhorse) of GitLab need to be built from source as a preliminary step for running tests.
This works well for the following reasons:
In [this MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79766), we introduced a new `build-components` job that:
- The pack-objects cache is enabled on all Gitaly servers on GitLab.com.
- The CI/CD [Git strategy setting](../ci/pipelines/settings.md#choose-the-default-git-strategy) for `gitlab-org/gitlab` is **Git clone**,
causing all jobs to fetch the same data, which maximizes the cache hit ratio.
- We use [shallow clone](../ci/pipelines/settings.md#limit-the-number-of-changes-fetched-during-clone) to avoid downloading the full Git
history for every job.
- runs automatically for all GitLab.com `gitlab-org/gitlab` scheduled pipelines
- runs automatically for any `master` commit that touches the `workhorse/` folder
- is manual for GitLab.com's `gitlab-org`'s MRs
This job tries to download a generic package that contains GitLab Workhorse binaries needed in the GitLab test suite (under `tmp/tests/gitlab-workhorse`).
- If the package URL returns a 404:
1. It runs `scripts/setup-test-env`, so that the GitLab Workhorse binaries are built.
1. It then creates an archive which contains the binaries and upload it [as a generic package](https://gitlab.com/gitlab-org/gitlab/-/packages/).
- Otherwise, if the package already exists, it exit the job successfully.
We also changed the `setup-test-env` job to:
1. First download the GitLab Workhorse generic package build and uploaded by `build-components`.
1. If the package is retrieved successfully, its content is placed in the right folder (i.e. `tmp/tests/gitlab-workhorse`), preventing the building of the binaries when `scripts/setup-test-env` is run later on.
1. If the package URL returns a 404, the behavior doesn't change compared to the current one: the GitLab Workhorse binaries are built as part of `scripts/setup-test-env`.
NOTE:
The version of the package is the workhorse tree SHA (i.e. `git rev-parse HEAD:workhorse`).
### Pre-clone step

View File

@ -9,77 +9,146 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/196455) in GitLab 12.9 for groups.
Value stream analytics measures the time spent to go from an
[idea to production](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#from-idea-to-production-with-gitlab)
(also known as cycle time) for each of your projects or groups. Value stream analytics displays the median time
spent in each stage defined in the process.
Value stream analytics provides metrics about each stage of your software development process.
Value stream analytics can help you quickly determine the velocity of a given
group. It points to bottlenecks in the development process, enabling management
to uncover, triage, and identify the root cause of slowdowns in the software development life cycle.
Use value stream analytics to identify:
For information on how to contribute to the development of value stream analytics, see our [contributor documentation](../../../development/value_stream_analytics.md).
- The amount of time it takes to go from an idea to production.
- The velocity of a given project.
- Bottlenecks in the development process.
- Factors that cause your software development lifecycle to slow down.
To view value stream analytics for groups:
Value stream analytics is also available for [projects](../../analytics/value_stream_analytics.md).
## View value stream analytics
> - Date range filter [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13216) in GitLab 12.4
> - Filtering [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13216) in GitLab 13.3
You must have at least the Reporter role to view value stream analytics for groups.
To view value stream analytics for your group:
1. On the top bar, select **Menu > Groups** and find your group.
1. On the left sidebar, select **Analytics > Value stream**.
1. To view metrics for each stage, above the **Filter results** text box, select a stage.
1. Optional. Filter the results:
1. Select the **Filter results** text box.
1. Select a parameter.
1. Select a value or enter text to refine the results.
1. To adjust the date range:
- In the **From** field, select a start date.
- In the **To** field, select an end date.
1. Optional. Sort results by ascending or descending:
- To sort by most recent or oldest workflow item, select the **Merge requests** or **Issues**
header. The header name differs based on the stage you select.
- To sort by most or least amount of time spent in each stage, select the **Time** header.
Value stream analytics at the group level includes data for the selected group and its subgroups.
The table shows a list of related workflow items for the selected stage. Based on the stage you select, this can be:
- CI/CD jobs
- Issues
- Merge requests
- Pipelines
A badge next to the workflow items table header shows the number of workflow items that
completed the selected stage.
## View metrics for each development stage
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/210315) in GitLab 13.0.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/323982) in GitLab 13.12.
Value stream analytics shows the median time spent by issues or merge requests in each development stage.
To view the median time spent in each stage by a group:
1. On the top bar, select **Menu > Groups** and find your group.
1. On the left sidebar, select **Analytics > Value stream**.
1. Optional. Filter the results:
1. Select the **Filter results** text box.
1. Select a parameter.
1. Select a value or enter text to refine the results.
1. To adjust the date range:
- In the **From** field, select a start date.
- In the **To** field, select an end date.
1. To view the metrics for each stage, above the **Filter results** text box, hover over a stage.
## View the lead time and cycle time for issues
Value stream analytics shows the lead time and cycle time for issues in your groups:
- Lead time: Median time from when the issue was created to when it was closed.
- Cycle time: Median time from first commit to issue closed. Commits are associated with issues when users [cross-link them in the commit message](../../project/issues/crosslinking_issues.md#from-commit-messages).
To view the lead time and cycle time for issues:
1. On the top bar, select **Menu > Groups** and find your group.
1. On the left sidebar, select **Analytics > Value stream**.
1. Optional. Filter the results:
1. Select the **Filter results** text box.
1. Select a parameter.
1. Select a value or enter text to refine the results.
1. To adjust the date range:
- In the **From** field, select a start date.
- In the **To** field, select an end date.
The **Lead Time** and **Cycle Time** metrics display below the **Filter results** text box.
## View lead time for changes for merge requests **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340150) in GitLab 14.5.
Lead time for changes is the median duration between when a merge request is merged and when it's deployed to production.
To view the lead time for changes for merge requests in your group:
1. On the top bar, select **Menu > Groups** and find your group.
1. On the left sidebar, select **Analytics > Value stream**.
1. Optional. Filter the results:
1. Select the **Filter results** text box.
1. Select a parameter.
1. Select a value or enter text to refine the results.
1. To adjust the date range:
- In the **From** field, select a start date.
- In the **To** field, select an end date.
The **Lead Time for Changes** metrics display below the **Filter results** text box.
## View number of successful deployments **(PREMIUM)**
> DORA API-based deployment metrics for value stream analytics for groups were [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/337256) from GitLab Ultimate to GitLab Premium in 14.3.
To view deployment metrics, you must have a
[production environment configured](../../../ci/environments/index.md#deployment-tier-of-environments).
Value stream analytics shows the following deployment metrics for your group:
- Deploys: The number of successful deployments in the date range.
- Deployment Frequency: The average number of successful deployments per day in the date range.
To view deployment metrics for your group:
1. On the top bar, select **Menu > Groups** and find your group.
1. On the left sidebar, select **Analytics > Value stream**.
1. Optional. Filter the results:
1. Select the **Filter results** text box.
1. Select a parameter.
1. Select a value or enter text to refine the results.
1. To adjust the date range:
- In the **From** field, select a start date.
- In the **To** field, select an end date.
The **Deploys** and **Deployment Frequency** metrics display below the **Filter results** text box.
Deployment metrics are calculated based on data from the
[DORA API](../../../api/dora/metrics.md#devops-research-and-assessment-dora-key-metrics-api).
NOTE:
[Value stream analytics for projects](../../analytics/value_stream_analytics.md) is also available.
In GitLab 13.9 and later, metrics are calculated based on when the deployment was finished.
In GitLab 13.8 and earlier, metrics are calculated based on when the deployment was created.
## Default stages
The stages tracked by value stream analytics by default represent the [GitLab flow](../../../topics/gitlab_flow.md).
These stages can be customized in value stream analytics for groups.
- **Issue** (Tracker)
- Time to schedule an issue (by milestone or by adding it to an issue board)
- **Plan** (Board)
- Time to first commit
- **Code** (IDE)
- Time to create a merge request
- **Test** (CI)
- Time it takes GitLab CI/CD to test your code
- **Review** (Merge Request/MR)
- Time spent on code review
- **Staging** (Continuous Deployment)
- Time between merging and deploying to production
## Filter the analytics data
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13216) in GitLab 13.3
GitLab provides the ability to filter analytics based on the following parameters:
- Milestones (Group level)
- Labels (Group level)
- Author
- Assignees
To filter results:
1. Select a group.
1. Click on the filter bar.
1. Select a parameter to filter by.
1. Select a value from the autocompleted results, or type to refine the results.
![Value stream analytics filter bar](img/vsa_filter_bar_v13_12.png "Active filter bar for value stream analytics")
### Date ranges
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13216) in GitLab 12.4.
GitLab provides the ability to filter analytics based on a date range.
Data is shown for workflow items created during the selected date range. To filter results:
1. Select a group.
1. Optionally select a project.
1. Select a date range using the available date pickers.
### Upcoming date filter change
## Upcoming date filter change
In the [epics](https://gitlab.com/groups/gitlab-org/-/epics/6046), we plan to alter
the date filter behavior to filter the end event time of the currently selected stage.
@ -92,82 +161,72 @@ If you were to look at the metrics for the last three months, this issue would n
the stage metrics. With the new date filter, this item would be included.
DISCLAIMER:
This page contains information related to upcoming products, features, and functionality.
This section contains information related to upcoming products, features, and functionality.
It is important to note that the information presented is for informational purposes only.
Please do not rely on this information for purchasing or planning purposes.
As with all projects, the items mentioned on this page are subject to change or delay.
The development, release, and timing of any products, features, or functionality remain at the
sole discretion of GitLab Inc.
## How metrics are measured
> DORA API-based deployment metrics for value stream analytics for groups were [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/337256) from GitLab Ultimate to GitLab Premium in 14.3.
The "Time" metrics near the top of the page are measured as follows:
- **Lead time**: median time from issue created to issue closed.
- **Cycle time**: median time from first commit to issue closed. (You can associate a commit with an
issue by [crosslinking in the commit message](../../project/issues/crosslinking_issues.md#from-commit-messages).)
- **Lead Time for Changes**: median time between when a merge request is merged and deployed to a
production environment for all merge requests deployed in the given time period.
[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340150) in GitLab 14.5.
- **Lead Time for Changes**: median duration between merge request merge and deployment to a production environment for all MRs deployed in the given time period. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340150) in GitLab 14.5.
The "Recent Activity" metrics near the top of the page are measured as follows:
- **New Issues:** the number of issues created in the date range.
- **Deploys:** the number of deployments to production in the date range.
- **Deployment Frequency:** the average number of deployments to production
per day in the date range.
To see deployment metrics, you must have a [production environment configured](../../../ci/environments/index.md#deployment-tier-of-environments).
NOTE:
In GitLab 13.9 and later, deployment metrics are calculated based on when the deployment was finished.
In GitLab 13.8 and earlier, deployment metrics are calculated based on when the deployment was created.
You can learn more about these metrics in our [analytics definitions](../../analytics/index.md).
![Value stream analytics time metrics](img/vsa_time_metrics_v13_12.png "Time metrics for value stream analytics")
## How the stages are measured
## How value stream analytics measures stages
Value stream analytics measures each stage from its start event to its end event.
For example, a stage might start when one label is added to an issue, and end when another label is added.
Value stream analytics excludes work in progress, meaning it ignores any items that have not reached the end event.
For example, a stage might start when a user adds a label to an issue, and ends when they add another label.
Items aren't included in the stage time calculation if they have not reached the end event.
Each stage of value stream analytics is further described in the table below.
| **Stage** | **Description** |
| --------- | --------------- |
| Issue | Measures the median time between creating an issue and taking action to solve it, by either labeling it or adding it to a milestone, whatever comes first. The label is tracked only if it already has an [issue board list](../../project/issue_board.md) created for it. |
| Plan | Measures the median time between the action you took for the previous stage, and pushing the first commit to the branch. The very first commit of the branch is the one that triggers the separation between **Plan** and **Code**, and at least one of the commits in the branch needs to contain the related issue number (for example, `#42`). If none of the commits in the branch mention the related issue number, it is not considered to the measurement time of the stage. |
| Code | Measures the median time between pushing a first commit (previous stage) and creating a merge request (MR) related to that commit. The key to keep the process tracked is to include the [issue closing pattern](../../project/issues/managing_issues.md#closing-issues-automatically) to the description of the merge request (for example, `Closes #xxx`, where `xxx` is the number of the issue related to this merge request). If the closing pattern is not present, then the calculation takes the creation time of the first commit in the merge request as the start time. |
| Test | Measures the median time to run the entire pipeline for that project. It's related to the time GitLab CI/CD takes to run every job for the commits pushed to that merge request defined in the previous stage. It is basically the start->finish time for all pipelines. |
| Review | Measures the median time taken to review the merge request that has a closing issue pattern, between its creation and until it's merged. |
| Staging | Measures the median time between merging the merge request with a closing issue pattern until the very first deployment to a [production environment](#how-the-production-environment-is-identified). If there isn't a production environment, this is not tracked. |
| Stage | Measurement method |
| ------- | -------------------- |
| Issue | The median time between creating an issue and taking action to solve it, by either labeling it or adding it to a milestone, whichever comes first. The label is tracked only if it already has an [issue board list](../../project/issue_board.md) created for it. |
| Plan | The median time between the action you took for the previous stage, and pushing the first commit to the branch. The first commit on the branch triggers the separation between **Plan** and **Code**. At least one of the commits in the branch must contain the related issue number (for example, `#42`). If none of the commits in the branch mention the related issue number, it is not considered in the measurement time of the stage. |
| Code | The median time between pushing a first commit (previous stage) and creating a merge request (MR) related to that commit. The key to keep the process tracked is to include the [issue closing pattern](../../project/issues/managing_issues.md#default-closing-pattern) in the description of the merge request. For example, `Closes #xxx`, where `xxx` is the number of the issue related to this merge request. If the closing pattern is not present, then the calculation uses the creation time of the first commit in the merge request as the start time. |
| Test | The median time to run the entire pipeline for that project. It's related to the time GitLab CI/CD takes to run every job for the commits pushed to that merge request. It is basically the start->finish time for all pipelines. |
| Review | The median time taken to review a merge request that has a closing issue pattern, between its creation and until it's merged. |
| Staging | The median time between merging a merge request that has a closing issue pattern until the very first deployment to a [production environment](#how-value-stream-analytics-identifies-the-production-environment). If there isn't a production environment, this is not tracked. |
How this works, behind the scenes:
## Example workflow
1. Issues and merge requests are grouped together in pairs, such that for each
`<issue, merge request>` pair, the merge request has the [issue closing pattern](../../project/issues/managing_issues.md#closing-issues-automatically)
for the corresponding issue. All other issues and merge requests are **not**
considered.
1. Then the `<issue, merge request>` pairs are filtered out by last XX days (specified
by the UI - default is 90 days). So it prohibits these pairs from being considered.
1. For the remaining `<issue, merge request>` pairs, we check the information that
we need for the stages, like issue creation date, merge request merge time,
and so on.
This example shows a workflow through all seven stages in one day.
To sum up, anything that doesn't follow [GitLab flow](../../../topics/gitlab_flow.md) is not tracked and the
value stream analytics dashboard does not present any data for:
If a stage does not include a start and a stop time, its data is not included in the median time.
In this example, milestones have been created and CI/CD for testing and setting environments is configured.
- Merge requests that do not close an issue.
- Issues not labeled with a label present in the issue board or for issues not assigned a milestone.
- Staging stage, if the project has no [production environment](#how-the-production-environment-is-identified).
- 09:00: Create issue. **Issue** stage starts.
- 11:00: Add issue to a milestone, start work on the issue, and create a branch locally.
**Issue** stage stops and **Plan** stage starts.
- 12:00: Make the first commit.
- 12:30: Make the second commit to the branch that mentions the issue number.
**Plan** stage stops and **Code** stage starts.
- 14:00: Push branch and create a merge request that contains the
[issue closing pattern](../../project/issues/managing_issues.md#closing-issues-automatically).
**Code** stage stops and **Test** and **Review** stages start.
- GitLab CI/CD takes 5 minutes to run scripts defined in [`.gitlab-ci.yml`](../../../ci/yaml/index.md).
- 19:00: Merge the merge request. **Review** stage stops and **Staging** stage starts.
- 19:30: Deployment to the `production` environment finishes. **Staging** stops.
## How the production environment is identified
Value stream analytics records the following times for each stage:
- **Issue**: 09:00 to 11:00: 2 hrs
- **Plan**: 11:00 to 12:00: 1 hr
- **Code**: 12:00 to 14:00: 2 hrs
- **Test**: 5 minutes
- **Review**: 14:00 to 19:00: 5 hrs
- **Staging**: 19:00 to 19:30: 30 minutes
There are some additional considerations for this example:
- This example demonstrates that it doesn't matter if your first
commit doesn't mention the issue number, you can do this later in any commit
on the branch you are working on.
- The **Test** stage is used in the calculation for the overall time of
the cycle. It is included in the **Review** process, as every MR should be
tested.
- This example illustrates only **one cycle** of the seven stages. The value stream analytics dashboard
shows the median time for multiple cycles.
## How value stream analytics identifies the production environment
Value stream analytics identifies production environments by looking for project
[environments](../../../ci/yaml/index.md#environment) with a name matching any of these patterns:
@ -179,149 +238,21 @@ These patterns are not case-sensitive.
You can change the name of a project environment in your GitLab CI/CD configuration.
## Example workflow
Below is an example workflow of a single cycle that happens in a
single day through all noted stages. Note that if a stage does not include a start
and a stop time, its data is not included in the median time. It is assumed that
milestones are created and a CI for testing and setting environments is configured.
a start and a stop mark, it is not measured and hence not calculated in the median
time. It is assumed that milestones are created and CI for testing and setting
environments is configured.
1. Issue is created at 09:00 (start of **Issue** stage).
1. Issue is added to a milestone at 11:00 (stop of **Issue** stage / start of
**Plan** stage).
1. Start working on the issue, create a branch locally and make one commit at
12:00.
1. Make a second commit to the branch which mentions the issue number at 12.30
(stop of **Plan** stage / start of **Code** stage).
1. Push branch and create a merge request that contains the
[issue closing pattern](../../project/issues/managing_issues.md#closing-issues-automatically)
in its description at 14:00 (stop of **Code** stage / start of **Test** and
**Review** stages).
1. The CI starts running your scripts defined in [`.gitlab-ci.yml`](../../../ci/yaml/index.md) and
takes 5min (stop of **Test** stage).
1. Review merge request, ensure that everything is OK and merge the merge
request at 19:00. (stop of **Review** stage / start of **Staging** stage).
1. Now that the merge request is merged, a deployment to the `production`
environment starts and finishes at 19:30 (stop of **Staging** stage).
From the above example you can conclude the time it took each stage to complete
as long as their total time:
- **Issue**: 2h (11:00 - 09:00)
- **Plan**: 1h (12:00 - 11:00)
- **Code**: 2h (14:00 - 12:00)
- **Test**: 5min
- **Review**: 5h (19:00 - 14:00)
- **Staging**: 30min (19:30 - 19:00)
A few notes:
- In the above example we demonstrated that it doesn't matter if your first
commit doesn't mention the issue number, you can do this later in any commit
of the branch you are working on.
- You can see that the **Test** stage is not calculated to the overall time of
the cycle, because it is included in the **Review** process (every MR should be
tested).
- The example above was just **one cycle** of the seven stages. Add multiple
cycles, calculate their median time and the result is what the dashboard of
value stream analytics is showing.
## Custom value streams
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12196) in GitLab 12.9.
The default stages are designed to work straight out of the box, but they might not be suitable for
all teams. Different teams use different approaches to building software, so some teams might want
to customize their value stream analytics.
Use custom value streams to create custom stages that align with your own development processes,
and hide default stages.
GitLab allows users to create multiple value streams, hide default stages and create custom stages
that align better to their development workflow.
### Stage path
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/210315) in GitLab 13.0.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/323982) in GitLab 13.12.
![Value stream path navigation](img/vsa_path_nav_v13_11.png "Value stream path navigation")
Stages are visually depicted as a horizontal process flow. Selecting a stage updates the content
below the value stream.
The stage time is displayed next to the name of each stage, in the following format:
| Symbol | Description |
|--------|-------------|
| `m` | Minutes |
| `h` | Hours |
| `d` | Days |
| `w` | Weeks |
| `M` | Months |
Hovering over a stage item displays a popover with the following information:
- Start event description for the given stage
- End event description
- Median time items took to complete the stage
- Number of items that completed the stage
### Stream overview
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/321438) in GitLab 13.11.
![Value stream analytics overview](img/vsa_overview_stage_v13_11.png "VSA overview")
The stream overview provides access to key metrics and charts summarizing all the stages in the value stream
based on selected filters.
Shown metrics and charts includes:
- [Lead time](#how-metrics-are-measured)
- [Cycle time](#how-metrics-are-measured)
- [Total time chart](#total-time-chart)
- [Tasks by type chart](#type-of-work---tasks-by-type-chart)
### Stage table
> Sorting the stage table [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/301082) in GitLab 13.12.
![Value stream analytics stage table](img/vsa_stage_table_v14_7.png "VSA stage table")
The stage table shows a list of related workflow items for the selected stage. This can include:
- CI/CD jobs
- Issues
- Merge requests
- Pipelines
A little badge next to the workflow items table header shows the number of workflow items that
completed the selected stage.
The stage table also includes the **Time** column, which shows how long it takes each item to pass
through the selected value stream stage.
The stage table is not displayed on the stream [Overview](#stream-overview).
The workflow item column (first column) is ordered by end event.
To sort the stage table by a table column, select the table header.
You can sort in ascending or descending order. To find items that spent the most time in a stage,
potentially causing bottlenecks in your value stream, sort the table by the **Time** column.
From there, select individual items to drill in and investigate how delays are happening.
To see which items most recently exited the stage, sort by the work item column on the left.
The table displays 20 items per page. If there are more than 20 items, you can use the
**Prev** and **Next** buttons to navigate through the pages.
### Creating a value stream
### Create a value stream
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/221202) in GitLab 13.3
A default value stream is readily available for each group. You can create additional value streams
based on the different areas of work that you would like to measure.
Once created, a new value stream includes the [seven stages](#default-stages) that follow
Once created, a new value stream includes the stages that follow
[GitLab workflow](../../../topics/gitlab_flow.md)
best practices. You can customize this flow by adding, hiding or re-ordering stages.
@ -336,7 +267,7 @@ To create a value stream:
![New value stream](img/new_value_stream_v13_12.png "Creating a new value stream")
#### Creating a value stream with stages
### Creating a value stream with stages
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50229) in GitLab 13.7.
> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55572) in GitLab 13.10.
@ -364,7 +295,7 @@ To create a value stream with stages:
![Custom stage actions](img/vsa_custom_stage_v13_10.png "Custom stage actions")
1. Select **Create Value Stream**.
#### Label-based stages
### Label-based stages
The pre-defined start and end events can cover many use cases involving both issues and merge requests.
@ -379,7 +310,7 @@ In this example, we'd like to measure times for deployment from a staging enviro
![Label-based value stream analytics stage](img/vsa_label_based_stage_v14_0.png "Creating a label-based value stream analytics stage")
### Editing a value stream
### Edit a value stream
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/267537) in GitLab 13.10.
@ -399,7 +330,7 @@ After you create a value stream, you can customize it to suit your purposes. To
1. Optional. To undo any modifications, select **Restore value stream defaults**.
1. Select **Save Value Stream**.
### Deleting a value stream
### Delete a value stream
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/221205) in GitLab 13.4.
@ -440,17 +371,3 @@ toggled to show data for merge requests and further refined for specific group-l
By default the top group-level labels (max. 10) are pre-selected, with the ability to
select up to a total of 15 labels.
## Permissions
To access value stream analytics for groups, users must have at least the Reporter role.
You can [read more about permissions](../../permissions.md) in general.
## More resources
Learn more about value stream analytics in the following resources:
- [Value stream analytics feature page](https://about.gitlab.com/stages-devops-lifecycle/value-stream-analytics/).
- [Value stream analytics feature preview](https://about.gitlab.com/blog/2016/09/16/feature-preview-introducing-cycle-analytics/).
- [Value stream analytics feature highlight](https://about.gitlab.com/blog/2016/09/21/cycle-analytics-feature-highlight/).

View File

@ -4,7 +4,7 @@ group: Workspace
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
---
# Reserved project and group names
# Reserved project and group names **(FREE)**
Not all project & group names are allowed because they would conflict with
existing routes used by GitLab.
@ -45,7 +45,7 @@ It is currently not possible to create a project with the following names:
## Reserved group names
Currently the following names are reserved as top level groups:
Currently, the following names are reserved as top level groups:
- `\-`
- `.well-known`

View File

@ -46,7 +46,7 @@ module Gitlab
end
def table_to_model_mapping
@table_to_model_mapping ||= models.each_with_object({}) { |model, h| h[model.table_name] = model }
@table_to_model_mapping ||= models.index_by(&:table_name)
end
def table_to_model(table_name)

View File

@ -63,7 +63,7 @@ module Gitlab
@repository
.languages
.first(MAX_LANGUAGES)
.to_h { |l| [l[:label], l] }
.index_by { |l| l[:label] }
end
end
end

View File

@ -160,7 +160,7 @@
"prosemirror-model": "^1.16.1",
"prosemirror-state": "^1.3.4",
"prosemirror-tables": "^1.1.1",
"prosemirror-view": "^1.23.6",
"prosemirror-view": "^1.23.7",
"raphael": "^2.2.7",
"raw-loader": "^4.0.2",
"scrollparent": "^2.0.1",

View File

@ -572,7 +572,7 @@
<li data-sourcepos="8:1-8:149">The concert starts at <time datetime="20:00">20:00</time> and you'll be able to enjoy the band for at least <time datetime="PT2H30M">2h 30m</time>.</li>
<li data-sourcepos="9:1-9:62">Press <kbd>Ctrl</kbd> + <kbd>C</kbd> to copy text (Windows).</li>
<li data-sourcepos="10:1-10:105">WWF's goal is to: <q>Build a future where people live in harmony with nature.</q> We hope they succeed.</li>
<li data-sourcepos="11:1-11:79">The error occurred was: <samp>Keyboard not found. Press F1 to continue.</samp>
<li data-sourcepos="11:1-11:80">The error occurred was: <samp>Keyboard not found. Press F1 to continue.</samp>
</li>
<li data-sourcepos="12:1-12:136">The area of a triangle is: 1/2 x <var>b</var> x <var>h</var>, where <var>b</var> is the base, and <var>h</var> is the vertical height.</li>
<li data-sourcepos="13:1-13:35"><ruby>漢<rt>ㄏㄢˋ</rt></ruby></li>

View File

@ -21,6 +21,7 @@ exports[`Blob Header Default Actions rendering matches the snapshot 1`] = `
class="gl-sm-display-flex file-actions"
>
<viewer-switcher-stub
docicon="document"
value="simple"
/>

View File

@ -159,5 +159,20 @@ describe('Blob Header Default Actions', () => {
await nextTick();
expect(wrapper.vm.$emit).not.toHaveBeenCalled();
});
it('sets different icons depending on the blob file type', async () => {
factory();
expect(wrapper.vm.blobSwitcherDocIcon).toBe('document');
await wrapper.setProps({
blob: {
...Blob,
richViewer: {
...Blob.richViewer,
fileType: 'csv',
},
},
});
expect(wrapper.vm.blobSwitcherDocIcon).toBe('table');
});
});
});

View File

@ -2,6 +2,7 @@ import { GlLoadingIcon, GlTable } from '@gitlab/ui';
import { getAllByRole } from '@testing-library/dom';
import { shallowMount, mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import Papa from 'papaparse';
import CsvViewer from '~/blob/csv/csv_viewer.vue';
import PapaParseAlert from '~/vue_shared/components/papa_parse_alert.vue';
@ -11,10 +12,15 @@ const brokenCsv = '{\n "json": 1,\n "key": [1, 2, 3]\n}';
describe('app/assets/javascripts/blob/csv/csv_viewer.vue', () => {
let wrapper;
const createComponent = ({ csv = validCsv, mountFunction = shallowMount } = {}) => {
const createComponent = ({
csv = validCsv,
remoteFile = false,
mountFunction = shallowMount,
} = {}) => {
wrapper = mountFunction(CsvViewer, {
propsData: {
csv,
remoteFile,
},
});
};
@ -73,4 +79,22 @@ describe('app/assets/javascripts/blob/csv/csv_viewer.vue', () => {
expect(getAllByRole(wrapper.element, 'row', { name: /Three/i })).toHaveLength(1);
});
});
describe('when csv prop is path and indicates a remote file', () => {
it('should render call parse with download flag true', async () => {
const path = 'path/to/remote/file.csv';
jest.spyOn(Papa, 'parse').mockImplementation((_, { complete }) => {
complete({ data: validCsv.split(','), errors: [] });
});
createComponent({ csv: path, remoteFile: true });
expect(Papa.parse).toHaveBeenCalledWith(path, {
download: true,
skipEmptyLines: true,
complete: expect.any(Function),
});
await nextTick;
expect(wrapper.vm.items).toEqual(validCsv.split(','));
});
});
});

View File

@ -335,21 +335,6 @@ describe('Time series component', () => {
expect(formattedTooltipData.content).toBe(annotationsMetadata.tooltipData.content);
});
});
describe('onResize', () => {
const mockWidth = 233;
beforeEach(() => {
jest.spyOn(Element.prototype, 'getBoundingClientRect').mockImplementation(() => ({
width: mockWidth,
}));
wrapper.vm.onResize();
});
it('sets area chart width', () => {
expect(wrapper.vm.width).toBe(mockWidth);
});
});
});
describe('computed', () => {

View File

@ -0,0 +1,27 @@
import { shallowMount } from '@vue/test-utils';
import CsvViewer from '~/repository/components/blob_viewers/csv_viewer.vue';
describe('CSV Viewer', () => {
let wrapper;
const DEFAULT_BLOB_DATA = {
rawPath: 'some/file.csv',
name: 'file.csv',
};
const createComponent = () => {
wrapper = shallowMount(CsvViewer, {
propsData: { blob: DEFAULT_BLOB_DATA },
stubs: ['CsvViewer'],
});
};
const findCsvViewerComp = () => wrapper.find('[data-testid="csv"]');
it('renders a Source Editor component', () => {
createComponent();
expect(findCsvViewerComp().exists()).toBe(true);
expect(findCsvViewerComp().props('remoteFile')).toBeTruthy();
expect(findCsvViewerComp().props('csv')).toBe(DEFAULT_BLOB_DATA.rawPath);
});
});

View File

@ -127,5 +127,18 @@ describe('ColorPicker', () => {
expect(wrapper.emitted().input[0]).toStrictEqual([setColor]);
});
it('shows the suggested colors passed using props', () => {
const customColors = {
'#ff0000': 'Red',
'#808080': 'Gray',
};
createComponent(shallowMount, { suggestedColors: customColors });
expect(description()).toBe('Enter any color or choose one of the suggested colors below.');
expect(presetColors()).toHaveLength(2);
expect(presetColors().at(0).attributes('title')).toBe('Red');
expect(presetColors().at(1).attributes('title')).toBe('Gray');
});
});
});

View File

@ -449,11 +449,15 @@ RSpec.describe Projects::DestroyService, :aggregate_failures do
end
context 'when an error is raised deleting snippets' do
let(:error_message) { 'foo' }
it 'does not delete project' do
allow_next_instance_of(Snippets::BulkDestroyService) do |instance|
allow(instance).to receive(:execute).and_return(ServiceResponse.error(message: 'foo'))
allow(instance).to receive(:execute).and_return(ServiceResponse.error(message: error_message))
end
expect(Gitlab::AppLogger).to receive(:error).with("Snippet deletion failed on #{project.full_path} with the following message: #{error_message}")
expect(Gitlab::AppLogger).to receive(:error).with(/Failed to remove project snippets/)
expect(destroy_project(project, user)).to be_falsey
expect(project.gitlab_shell.repository_exists?(project.repository_storage, path + '.git')).to be_truthy
end

View File

@ -9709,10 +9709,10 @@ prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transfor
dependencies:
prosemirror-model "^1.0.0"
prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.16.5, prosemirror-view@^1.23.6:
version "1.23.6"
resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.23.6.tgz#f514b3166942cb70aac4ac24d0a28c21c3897608"
integrity sha512-B4DAzriNpI/AVoW0Lu6SVfX00jZZQxOVwdBQEjWlRbCdT9V0pvk4GQJ3JTFaib+b6BcPdRZ3MjWXz2xvV1rblA==
prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.16.5, prosemirror-view@^1.23.6, prosemirror-view@^1.23.7:
version "1.23.7"
resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.23.7.tgz#f003af94445ef456e397c18cf4bb995e7072097f"
integrity sha512-ugY+g/4UI2Ree1zzdvbyQWF2KpbFa7kxKMLHaEJcxiPaErnZiD5wZFqIgFinc7fY2v/QM3DLnJ++2I45ULRdrg==
dependencies:
prosemirror-model "^1.16.0"
prosemirror-state "^1.0.0"