Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
93b6ee78bf
commit
61b943c213
|
@ -1,9 +1,6 @@
|
|||
---
|
||||
# Cop supports --auto-correct.
|
||||
RSpec/ScatteredLet:
|
||||
# Offense count: 720
|
||||
# Temporarily disabled due to too many offenses
|
||||
Enabled: false
|
||||
Exclude:
|
||||
- 'ee/spec/features/groups/group_roadmap_spec.rb'
|
||||
- 'ee/spec/features/merge_trains/two_merge_requests_on_train_spec.rb'
|
||||
|
@ -19,10 +16,10 @@ RSpec/ScatteredLet:
|
|||
- 'ee/spec/graphql/types/instance_security_dashboard_type_spec.rb'
|
||||
- 'ee/spec/helpers/ee/subscribable_banner_helper_spec.rb'
|
||||
- 'ee/spec/helpers/trial_status_widget_helper_spec.rb'
|
||||
- 'ee/spec/lib/banzai/reference_parser/iteration_parser_spec.rb'
|
||||
- 'ee/spec/lib/ee/audit/compliance_framework_changes_auditor_spec.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/ci/config_spec.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/email/handler/service_desk_handler_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/background_migration/migrate_requirements_to_work_items_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/ci/parsers/security/dast_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/ci/parsers/security/formatters/dependency_list_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/ci/templates/dast_api_gitlab_ci_yaml_spec.rb'
|
||||
|
@ -62,9 +59,12 @@ RSpec/ScatteredLet:
|
|||
- 'ee/spec/requests/api/graphql/project/pipelines/dast_profile_spec.rb'
|
||||
- 'ee/spec/requests/api/internal/base_spec.rb'
|
||||
- 'ee/spec/requests/api/projects_spec.rb'
|
||||
- 'ee/spec/requests/api/settings_spec.rb'
|
||||
- 'ee/spec/requests/api/vulnerability_findings_spec.rb'
|
||||
- 'ee/spec/requests/git_http_geo_spec.rb'
|
||||
- 'ee/spec/serializers/license_compliance/collapsed_comparer_entity_spec.rb'
|
||||
- 'ee/spec/serializers/status_page/incident_serializer_spec.rb'
|
||||
- 'ee/spec/services/app_sec/dast/scan_configs/fetch_service_spec.rb'
|
||||
- 'ee/spec/services/app_sec/dast/scanner_profiles/update_service_spec.rb'
|
||||
- 'ee/spec/services/arkose/blocked_users_report_service_spec.rb'
|
||||
- 'ee/spec/services/arkose/user_verification_service_spec.rb'
|
||||
|
@ -88,13 +88,13 @@ RSpec/ScatteredLet:
|
|||
- 'ee/spec/services/requirements_management/update_requirement_service_spec.rb'
|
||||
- 'ee/spec/services/search/group_service_spec.rb'
|
||||
- 'ee/spec/services/search/project_service_spec.rb'
|
||||
- 'ee/spec/services/security/ingestion/tasks/update_vulnerability_uuids_spec.rb'
|
||||
- 'ee/spec/services/todo_service_spec.rb'
|
||||
- 'ee/spec/views/shared/_mirror_update_button.html.haml_spec.rb'
|
||||
- 'ee/spec/views/subscriptions/groups/edit.html.haml_spec.rb'
|
||||
- 'ee/spec/workers/compliance_management/merge_requests/compliance_violations_worker_spec.rb'
|
||||
- 'ee/spec/workers/concerns/update_orchestration_policy_configuration_spec.rb'
|
||||
- 'qa/qa/specs/features/ee/browser_ui/1_manage/group/group_audit_logs_1_spec.rb'
|
||||
- 'qa/qa/specs/features/ee/browser_ui/1_manage/project/project_audit_logs_spec.rb'
|
||||
- 'spec/controllers/projects/artifacts_controller_spec.rb'
|
||||
- 'spec/controllers/projects/deploy_keys_controller_spec.rb'
|
||||
- 'spec/controllers/projects/environments_controller_spec.rb'
|
||||
|
@ -126,14 +126,19 @@ RSpec/ScatteredLet:
|
|||
- 'spec/lib/banzai/reference_parser/project_parser_spec.rb'
|
||||
- 'spec/lib/banzai/reference_parser/snippet_parser_spec.rb'
|
||||
- 'spec/lib/banzai/reference_parser/user_parser_spec.rb'
|
||||
- 'spec/lib/bulk_imports/pipeline/runner_spec.rb'
|
||||
- 'spec/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline_spec.rb'
|
||||
- 'spec/lib/gitlab/asciidoc/include_processor_spec.rb'
|
||||
- 'spec/lib/gitlab/auth/ldap/person_spec.rb'
|
||||
- 'spec/lib/gitlab/auth/saml/auth_hash_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/backfill_imported_issue_search_data_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/copy_ci_builds_columns_to_security_scans_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/disable_legacy_open_source_license_for_inactive_public_projects_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/encrypt_static_object_token_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/legacy_uploads_migrator_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/nullify_orphan_runner_id_on_ci_builds_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/reset_too_many_tags_skipped_registry_imports_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/set_legacy_open_source_license_available_for_non_public_projects_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url_spec.rb'
|
||||
- 'spec/lib/gitlab/ci/config/external/file/artifact_spec.rb'
|
||||
- 'spec/lib/gitlab/ci/pipeline/chain/helpers_spec.rb'
|
||||
|
@ -162,6 +167,7 @@ RSpec/ScatteredLet:
|
|||
- 'spec/lib/gitlab/git/blame_spec.rb'
|
||||
- 'spec/lib/gitlab/git/diff_collection_spec.rb'
|
||||
- 'spec/lib/gitlab/git_access_spec.rb'
|
||||
- 'spec/lib/gitlab/github_import/importer/single_endpoint_issue_events_importer_spec.rb'
|
||||
- 'spec/lib/gitlab/github_import/parallel_scheduling_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/group/relation_tree_restorer_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/project/export_task_spec.rb'
|
||||
|
@ -182,7 +188,6 @@ RSpec/ScatteredLet:
|
|||
- 'spec/lib/gitlab/spamcheck/client_spec.rb'
|
||||
- 'spec/lib/gitlab/template/finders/global_template_finder_spec.rb'
|
||||
- 'spec/lib/gitlab/tree_summary_spec.rb'
|
||||
- 'spec/lib/gitlab/usage/service_ping_report_spec.rb'
|
||||
- 'spec/lib/gitlab/usage_data_metrics_spec.rb'
|
||||
- 'spec/lib/gitlab/utils/measuring_spec.rb'
|
||||
- 'spec/lib/gitlab/zentao/client_spec.rb'
|
||||
|
@ -236,6 +241,7 @@ RSpec/ScatteredLet:
|
|||
- 'spec/requests/api/project_clusters_spec.rb'
|
||||
- 'spec/requests/api/project_export_spec.rb'
|
||||
- 'spec/requests/api/rubygem_packages_spec.rb'
|
||||
- 'spec/requests/jira_routing_spec.rb'
|
||||
- 'spec/requests/projects/releases_controller_spec.rb'
|
||||
- 'spec/rubocop/cop/migration/update_column_in_batches_spec.rb'
|
||||
- 'spec/scripts/pipeline_test_report_builder_spec.rb'
|
||||
|
@ -277,6 +283,8 @@ RSpec/ScatteredLet:
|
|||
- 'spec/services/system_notes/design_management_service_spec.rb'
|
||||
- 'spec/services/system_notes/merge_requests_service_spec.rb'
|
||||
- 'spec/services/todo_service_spec.rb'
|
||||
- 'spec/services/web_hook_service_spec.rb'
|
||||
- 'spec/services/work_items/update_service_spec.rb'
|
||||
- 'spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb'
|
||||
- 'spec/tasks/gitlab/artifacts/migrate_rake_spec.rb'
|
||||
- 'spec/workers/concerns/gitlab/github_import/object_importer_spec.rb'
|
||||
|
|
|
@ -1 +1 @@
|
|||
1c907781819bf8810e15578f3d4d2b25e3ca1053
|
||||
f8e688fbf64938cf8563f765c040af39f33e0790
|
||||
|
|
4
Gemfile
4
Gemfile
|
@ -56,7 +56,7 @@ gem 'omniauth-authentiq', '~> 0.3.3'
|
|||
gem 'gitlab-omniauth-openid-connect', '~> 0.9.0', require: 'omniauth_openid_connect'
|
||||
gem 'omniauth-salesforce', '~> 1.0.5'
|
||||
gem 'omniauth-atlassian-oauth2', '~> 0.2.0'
|
||||
gem 'rack-oauth2', '~> 1.19.0'
|
||||
gem 'rack-oauth2', '~> 1.21.2'
|
||||
gem 'jwt', '~> 2.1.0'
|
||||
|
||||
# Kerberos authentication. EE-only
|
||||
|
@ -187,7 +187,7 @@ gem 'rack', '~> 2.2.4'
|
|||
gem 'rack-timeout', '~> 0.6.0', require: 'rack/timeout/base'
|
||||
|
||||
group :puma do
|
||||
gem 'puma', '~> 5.6.2', require: false
|
||||
gem 'puma', '~> 5.6.4', require: false
|
||||
gem 'puma_worker_killer', '~> 0.3.1', require: false
|
||||
gem 'sd_notify', '~> 0.1.0', require: false
|
||||
end
|
||||
|
|
|
@ -1005,7 +1005,7 @@ GEM
|
|||
tty-markdown
|
||||
tty-prompt
|
||||
public_suffix (4.0.7)
|
||||
puma (5.6.2)
|
||||
puma (5.6.4)
|
||||
nio4r (~> 2.0)
|
||||
puma_worker_killer (0.3.1)
|
||||
get_process_mem (~> 0.2)
|
||||
|
@ -1020,7 +1020,7 @@ GEM
|
|||
rack (>= 1.0, < 3)
|
||||
rack-cors (1.1.1)
|
||||
rack (>= 2.0.0)
|
||||
rack-oauth2 (1.19.0)
|
||||
rack-oauth2 (1.21.2)
|
||||
activesupport
|
||||
attr_required
|
||||
httpclient
|
||||
|
@ -1670,12 +1670,12 @@ DEPENDENCIES
|
|||
pry-byebug
|
||||
pry-rails (~> 0.3.9)
|
||||
pry-shell (~> 0.5.0)
|
||||
puma (~> 5.6.2)
|
||||
puma (~> 5.6.4)
|
||||
puma_worker_killer (~> 0.3.1)
|
||||
rack (~> 2.2.4)
|
||||
rack-attack (~> 6.6.0)
|
||||
rack-cors (~> 1.1.0)
|
||||
rack-oauth2 (~> 1.19.0)
|
||||
rack-oauth2 (~> 1.21.2)
|
||||
rack-proxy (~> 0.7.2)
|
||||
rack-timeout (~> 0.6.0)
|
||||
rails (~> 6.1.4.7)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { GlLink, GlTableLite, GlDropdownItem, GlDropdown, GlIcon, GlButton } from '@gitlab/ui';
|
||||
import { GlLink, GlTableLite, GlDropdownItem, GlDropdown, GlButton } from '@gitlab/ui';
|
||||
import { last } from 'lodash';
|
||||
import { numberToHumanSize } from '~/lib/utils/number_utils';
|
||||
import { __ } from '~/locale';
|
||||
|
@ -18,7 +18,6 @@ export default {
|
|||
components: {
|
||||
GlLink,
|
||||
GlTableLite,
|
||||
GlIcon,
|
||||
GlDropdown,
|
||||
GlDropdownItem,
|
||||
GlButton,
|
||||
|
@ -77,7 +76,7 @@ export default {
|
|||
label: '',
|
||||
hide: !this.canDelete,
|
||||
class: 'gl-text-right',
|
||||
tdClass: 'gl-w-4',
|
||||
tdClass: 'gl-w-4 gl-pt-3!',
|
||||
},
|
||||
].filter((c) => !c.hide);
|
||||
},
|
||||
|
@ -102,6 +101,7 @@ export default {
|
|||
},
|
||||
i18n: {
|
||||
deleteFile: __('Delete file'),
|
||||
moreActionsText: __('More actions'),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -156,10 +156,14 @@ export default {
|
|||
</template>
|
||||
|
||||
<template #cell(actions)="{ item }">
|
||||
<gl-dropdown category="tertiary" right>
|
||||
<template #button-content>
|
||||
<gl-icon name="ellipsis_v" />
|
||||
</template>
|
||||
<gl-dropdown
|
||||
category="tertiary"
|
||||
icon="ellipsis_v"
|
||||
:text-sr-only="true"
|
||||
:text="$options.i18n.moreActionsText"
|
||||
no-caret
|
||||
right
|
||||
>
|
||||
<gl-dropdown-item data-testid="delete-file" @click="$emit('delete-file', item)">
|
||||
{{ $options.i18n.deleteFile }}
|
||||
</gl-dropdown-item>
|
||||
|
|
|
@ -7,6 +7,10 @@ import { BACK_URL_PARAM } from '~/releases/constants';
|
|||
export default {
|
||||
i18n: {
|
||||
editButton: __('Edit this release'),
|
||||
historical: __('Historical release'),
|
||||
historicalTooltip: __(
|
||||
'This release was created with a date in the past. Evidence collection at the moment of the release is unavailable.',
|
||||
),
|
||||
},
|
||||
name: 'ReleaseBlockHeader',
|
||||
components: {
|
||||
|
@ -65,6 +69,14 @@ export default {
|
|||
<gl-badge v-if="release.upcomingRelease" variant="warning" class="align-middle">{{
|
||||
__('Upcoming Release')
|
||||
}}</gl-badge>
|
||||
<gl-badge
|
||||
v-else-if="release.historicalRelease"
|
||||
v-gl-tooltip
|
||||
:title="$options.i18n.historicalTooltip"
|
||||
class="gl-vertical-align-middle"
|
||||
>
|
||||
{{ $options.i18n.historical }}
|
||||
</gl-badge>
|
||||
</h2>
|
||||
<gl-button
|
||||
v-if="editLink"
|
||||
|
|
|
@ -8,6 +8,7 @@ fragment Release on Release {
|
|||
releasedAt
|
||||
createdAt
|
||||
upcomingRelease
|
||||
historicalRelease
|
||||
assets {
|
||||
__typename
|
||||
count
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#import "../fragments/release.fragment.graphql"
|
||||
|
||||
query allReleases(
|
||||
$fullPath: ID!
|
||||
$first: Int
|
||||
|
@ -12,88 +14,7 @@ query allReleases(
|
|||
releases(first: $first, last: $last, before: $before, after: $after, sort: $sort) {
|
||||
__typename
|
||||
nodes {
|
||||
__typename
|
||||
id
|
||||
name
|
||||
tagName
|
||||
tagPath
|
||||
descriptionHtml
|
||||
releasedAt
|
||||
createdAt
|
||||
upcomingRelease
|
||||
assets {
|
||||
__typename
|
||||
count
|
||||
sources {
|
||||
__typename
|
||||
nodes {
|
||||
__typename
|
||||
format
|
||||
url
|
||||
}
|
||||
}
|
||||
links {
|
||||
__typename
|
||||
nodes {
|
||||
__typename
|
||||
id
|
||||
name
|
||||
url
|
||||
directAssetUrl
|
||||
linkType
|
||||
external
|
||||
}
|
||||
}
|
||||
}
|
||||
evidences {
|
||||
__typename
|
||||
nodes {
|
||||
__typename
|
||||
id
|
||||
filepath
|
||||
collectedAt
|
||||
sha
|
||||
}
|
||||
}
|
||||
links {
|
||||
__typename
|
||||
editUrl
|
||||
selfUrl
|
||||
openedIssuesUrl
|
||||
closedIssuesUrl
|
||||
openedMergeRequestsUrl
|
||||
mergedMergeRequestsUrl
|
||||
closedMergeRequestsUrl
|
||||
}
|
||||
commit {
|
||||
__typename
|
||||
id
|
||||
sha
|
||||
webUrl
|
||||
title
|
||||
}
|
||||
author {
|
||||
__typename
|
||||
id
|
||||
webUrl
|
||||
avatarUrl
|
||||
username
|
||||
}
|
||||
milestones {
|
||||
__typename
|
||||
nodes {
|
||||
__typename
|
||||
id
|
||||
title
|
||||
description
|
||||
webPath
|
||||
stats {
|
||||
__typename
|
||||
totalIssuesCount
|
||||
closedIssuesCount
|
||||
}
|
||||
}
|
||||
}
|
||||
...Release
|
||||
}
|
||||
pageInfo {
|
||||
__typename
|
||||
|
|
|
@ -12,6 +12,7 @@ const convertScalarProperties = (graphQLRelease) =>
|
|||
'description',
|
||||
'descriptionHtml',
|
||||
'upcomingRelease',
|
||||
'historicalRelease',
|
||||
]);
|
||||
|
||||
const convertDateProperties = ({ releasedAt }) => ({
|
||||
|
|
|
@ -114,7 +114,7 @@ export default {
|
|||
return this.workItem?.mockWidgets?.find((widget) => widget.type === WIDGET_TYPE_LABELS);
|
||||
},
|
||||
workItemWeight() {
|
||||
return this.workItem?.mockWidgets?.find((widget) => widget.type === WIDGET_TYPE_WEIGHT);
|
||||
return this.workItem?.widgets?.find((widget) => widget.type === WIDGET_TYPE_WEIGHT);
|
||||
},
|
||||
workItemHierarchy() {
|
||||
return this.workItem?.widgets?.find((widget) => widget.type === WIDGET_TYPE_HIERARCHY);
|
||||
|
@ -142,7 +142,7 @@ export default {
|
|||
|
||||
<template>
|
||||
<section class="gl-pt-5">
|
||||
<gl-alert v-if="error" variant="danger" @dismiss="error = undefined">
|
||||
<gl-alert v-if="error" class="gl-mb-3" variant="danger" @dismiss="error = undefined">
|
||||
{{ error }}
|
||||
</gl-alert>
|
||||
|
||||
|
@ -236,6 +236,7 @@ export default {
|
|||
:weight="workItemWeight.weight"
|
||||
:work-item-id="workItem.id"
|
||||
:work-item-type="workItemType"
|
||||
@error="error = $event"
|
||||
/>
|
||||
</template>
|
||||
<work-item-description
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
<script>
|
||||
import { GlForm, GlFormGroup, GlFormInput } from '@gitlab/ui';
|
||||
import * as Sentry from '@sentry/browser';
|
||||
import { __ } from '~/locale';
|
||||
import Tracking from '~/tracking';
|
||||
import { TRACKING_CATEGORY_SHOW } from '../constants';
|
||||
import localUpdateWorkItemMutation from '../graphql/local_update_work_item.mutation.graphql';
|
||||
import { i18n, TRACKING_CATEGORY_SHOW } from '../constants';
|
||||
import updateWorkItemMutation from '../graphql/update_work_item.mutation.graphql';
|
||||
|
||||
/* eslint-disable @gitlab/require-i18n-strings */
|
||||
const allowedKeys = [
|
||||
|
@ -98,16 +99,34 @@ export default {
|
|||
},
|
||||
updateWeight(event) {
|
||||
this.isEditing = false;
|
||||
|
||||
const weight = Number(event.target.value);
|
||||
if (this.weight === weight) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.track('updated_weight');
|
||||
this.$apollo.mutate({
|
||||
mutation: localUpdateWorkItemMutation,
|
||||
variables: {
|
||||
input: {
|
||||
id: this.workItemId,
|
||||
weight: event.target.value === '' ? null : Number(event.target.value),
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: updateWorkItemMutation,
|
||||
variables: {
|
||||
input: {
|
||||
id: this.workItemId,
|
||||
weightWidget: {
|
||||
weight: event.target.value === '' ? null : weight,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
})
|
||||
.then(({ data }) => {
|
||||
if (data.workItemUpdate.errors.length) {
|
||||
throw new Error(data.workItemUpdate.errors.join('\n'));
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.$emit('error', i18n.updateError);
|
||||
Sentry.captureException(error);
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@ import produce from 'immer';
|
|||
import Vue from 'vue';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import createDefaultClient from '~/lib/graphql';
|
||||
import { WIDGET_TYPE_ASSIGNEES, WIDGET_TYPE_LABELS, WIDGET_TYPE_WEIGHT } from '../constants';
|
||||
import { WIDGET_TYPE_ASSIGNEES, WIDGET_TYPE_LABELS } from '../constants';
|
||||
import typeDefs from './typedefs.graphql';
|
||||
import workItemQuery from './work_item.query.graphql';
|
||||
|
||||
|
@ -10,7 +10,7 @@ export const temporaryConfig = {
|
|||
typeDefs,
|
||||
cacheConfig: {
|
||||
possibleTypes: {
|
||||
LocalWorkItemWidget: ['LocalWorkItemLabels', 'LocalWorkItemWeight'],
|
||||
LocalWorkItemWidget: ['LocalWorkItemLabels'],
|
||||
},
|
||||
typePolicies: {
|
||||
WorkItem: {
|
||||
|
@ -25,11 +25,6 @@ export const temporaryConfig = {
|
|||
allowScopedLabels: true,
|
||||
nodes: [],
|
||||
},
|
||||
{
|
||||
__typename: 'LocalWorkItemWeight',
|
||||
type: 'WEIGHT',
|
||||
weight: null,
|
||||
},
|
||||
]
|
||||
);
|
||||
},
|
||||
|
@ -56,13 +51,6 @@ export const resolvers = {
|
|||
assigneesWidget.assignees.nodes = [...input.assignees];
|
||||
}
|
||||
|
||||
if (input.weight != null) {
|
||||
const weightWidget = draftData.workItem.mockWidgets.find(
|
||||
(widget) => widget.type === WIDGET_TYPE_WEIGHT,
|
||||
);
|
||||
weightWidget.weight = input.weight;
|
||||
}
|
||||
|
||||
if (input.labels) {
|
||||
const labelsWidget = draftData.workItem.mockWidgets.find(
|
||||
(widget) => widget.type === WIDGET_TYPE_LABELS,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
enum LocalWidgetType {
|
||||
ASSIGNEES
|
||||
LABELS
|
||||
WEIGHT
|
||||
}
|
||||
|
||||
interface LocalWorkItemWidget {
|
||||
|
@ -19,11 +18,6 @@ type LocalWorkItemLabels implements LocalWorkItemWidget {
|
|||
nodes: [Label!]
|
||||
}
|
||||
|
||||
type LocalWorkItemWeight implements LocalWorkItemWidget {
|
||||
type: LocalWidgetType!
|
||||
weight: Int
|
||||
}
|
||||
|
||||
extend type WorkItem {
|
||||
mockWidgets: [LocalWorkItemWidget]
|
||||
}
|
||||
|
@ -32,7 +26,6 @@ input LocalUpdateWorkItemInput {
|
|||
id: WorkItemID!
|
||||
assignees: [UserCore!]
|
||||
labels: [Label]
|
||||
weight: Int
|
||||
}
|
||||
|
||||
type LocalWorkItemPayload {
|
||||
|
|
|
@ -28,6 +28,10 @@ fragment WorkItem on WorkItem {
|
|||
}
|
||||
}
|
||||
}
|
||||
... on WorkItemWidgetWeight {
|
||||
type
|
||||
weight
|
||||
}
|
||||
... on WorkItemWidgetHierarchy {
|
||||
type
|
||||
parent {
|
||||
|
|
|
@ -12,10 +12,6 @@ query workItem($id: WorkItemID!) {
|
|||
...Label
|
||||
}
|
||||
}
|
||||
... on LocalWorkItemWeight {
|
||||
type
|
||||
weight
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1507,7 +1507,7 @@ class MergeRequest < ApplicationRecord
|
|||
lock_mr
|
||||
yield
|
||||
ensure
|
||||
unlock_mr
|
||||
unlock_mr if locked?
|
||||
end
|
||||
|
||||
def update_and_mark_in_progress_merge_commit_sha(commit_id)
|
||||
|
|
|
@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366823
|
|||
milestone: '15.2'
|
||||
type: development
|
||||
group: group::source code
|
||||
default_enabled: false
|
||||
default_enabled: true
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: highlight_diffs_optimize_memory_usage
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92456
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/367890
|
||||
milestone: '15.3'
|
||||
type: development
|
||||
group: group::source code
|
||||
default_enabled: false
|
|
@ -79,6 +79,7 @@ POST /projects/:id/approvals
|
|||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in GitLab 12.3.
|
||||
> - Moved to GitLab Premium in 13.9.
|
||||
> - `protected_branches` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460) in GitLab 12.7.
|
||||
> - Pagination support [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31011) in GitLab 15.3 [with a flag](../administration/feature_flags.md) named `approval_rules_pagination`. Enabled by default.
|
||||
|
||||
You can request information about a project's approval rules using the following endpoint:
|
||||
|
||||
|
@ -86,6 +87,8 @@ You can request information about a project's approval rules using the following
|
|||
GET /projects/:id/approval_rules
|
||||
```
|
||||
|
||||
Use the `page` and `per_page` [pagination](index.md#offset-based-pagination) parameters to restrict the list of approval rules.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
|
@ -684,6 +687,7 @@ This includes additional information about the users who have already approved
|
|||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13712) in GitLab 12.3.
|
||||
> - Moved to GitLab Premium in 13.9.
|
||||
> - Pagination support [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31011) in GitLab 15.3 [with a flag](../administration/feature_flags.md) named `approval_rules_pagination`. Enabled by default.
|
||||
|
||||
You can request information about a merge request's approval rules using the following endpoint:
|
||||
|
||||
|
@ -691,6 +695,8 @@ You can request information about a merge request's approval rules using the fol
|
|||
GET /projects/:id/merge_requests/:merge_request_iid/approval_rules
|
||||
```
|
||||
|
||||
Use the `page` and `per_page` [pagination](index.md#offset-based-pagination) parameters to restrict the list of approval rules.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
|
|
|
@ -740,4 +740,15 @@ Example response:
|
|||
A release with a `released_at` attribute set to a future date is labeled
|
||||
as an **Upcoming Release** [in the UI](../../user/project/releases/index.md#upcoming-releases).
|
||||
|
||||
Additionally, if a [release is requested from the API](#list-releases), for each release with a `release_at` attribute set to a future date, an additional attribute `upcoming_release` (set to true) will be returned as part of the response.
|
||||
Additionally, if a [release is requested from the API](#list-releases), for each release with a `release_at` attribute set to a future date, an additional attribute `upcoming_release` (set to true) is returned as part of the response.
|
||||
|
||||
## Historical releases
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/199429) in GitLab 15.2.
|
||||
|
||||
A release with a `released_at` attribute set to a past date is labeled
|
||||
as an **Historical release** [in the UI](../../user/project/releases/index.md#historical-releases).
|
||||
|
||||
Additionally, if a [release is requested from the API](#list-releases), for each
|
||||
release with a `release_at` attribute set to a past date, an additional
|
||||
attribute `historical_release` (set to true) is returned as part of the response.
|
||||
|
|
|
@ -311,7 +311,7 @@ table.supported-languages ul {
|
|||
<p>
|
||||
Although Gradle with Java 8 is supported, there are other issues such that Android project builds are not supported at this time.
|
||||
Please see the backlog issue <a href="https://gitlab.com/gitlab-org/gitlab/-/issues/336866">Android support for Dependency
|
||||
Scanning (gemnasium-maven)</a> for more details. Also, Gradle is not supported when [FIPS mode](../../../development/fips_compliance.md#enable-fips-mode) is enabled.
|
||||
Scanning (gemnasium-maven)</a> for more details. Also, Gradle is not supported when <a href="https://docs.gitlab.com/ee/development/fips_compliance.html#enable-fips-mode">FIPS mode</a> is enabled.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
|
|
|
@ -127,7 +127,7 @@ To remove all resources:
|
|||
- cleanup
|
||||
|
||||
destroy:
|
||||
extends: .destroy
|
||||
extends: .terraform:destroy
|
||||
needs: []
|
||||
```
|
||||
|
||||
|
|
|
@ -298,6 +298,16 @@ release tag. When the `released_at` date and time has passed, the badge is autom
|
|||
|
||||
![An upcoming release](img/upcoming_release_v12_7.png)
|
||||
|
||||
## Historical releases
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/199429) in GitLab 15.2.
|
||||
|
||||
You can create a release in the past using either the
|
||||
[Releases API](../../../api/releases/index.md#historical-releases) or the UI. When you set
|
||||
a past `released_at` date, an **Historical release** badge is displayed next to
|
||||
the release tag. Due to being released in the past, [release evidence](#release-evidence)
|
||||
is not available.
|
||||
|
||||
## Edit a release
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26016) in GitLab 12.6.
|
||||
|
@ -828,10 +838,11 @@ keyword. Learn more in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issue
|
|||
|
||||
In the API:
|
||||
|
||||
- If you specify a future `released_at` date, the release becomes an **Upcoming Release**
|
||||
- If you specify a future `released_at` date, the release becomes an **Upcoming release**
|
||||
and the evidence is collected on the date of the release. You cannot collect
|
||||
release evidence before then.
|
||||
- If you use a past `released_at` date, no evidence is collected.
|
||||
- If you specify a past `released_at` date, the release becomes an **Historical
|
||||
release** and no evidence is collected.
|
||||
- If you do not specify a `released_at` date, release evidence is collected on the
|
||||
date the release is created.
|
||||
|
||||
|
|
|
@ -481,7 +481,11 @@ module API
|
|||
.execute(merge_request, AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
|
||||
end
|
||||
|
||||
present merge_request, with: Entities::MergeRequest, current_user: current_user, project: user_project
|
||||
if immediately_mergeable && !merge_request.merged?
|
||||
render_api_error!("Failed to merge branch", 422)
|
||||
else
|
||||
present merge_request, with: Entities::MergeRequest, current_user: current_user, project: user_project
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Returns the up to date merge-ref HEAD commit'
|
||||
|
|
|
@ -6,7 +6,8 @@ module Gitlab
|
|||
include Gitlab::Utils::Gzip
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
|
||||
EXPIRATION = 1.week
|
||||
EXPIRATION = 1.day
|
||||
PREVIOUS_EXPIRATION_PERIOD = 7.days
|
||||
VERSION = 2
|
||||
|
||||
delegate :diffable, to: :@diff_collection
|
||||
|
@ -69,19 +70,33 @@ module Gitlab
|
|||
|
||||
def key
|
||||
strong_memoize(:redis_key) do
|
||||
[
|
||||
'highlighted-diff-files',
|
||||
diffable.cache_key,
|
||||
VERSION,
|
||||
options = [
|
||||
diff_options,
|
||||
Feature.enabled?(:use_marker_ranges, diffable.project),
|
||||
Feature.enabled?(:diff_line_syntax_highlighting, diffable.project)
|
||||
].join(":")
|
||||
]
|
||||
|
||||
options_for_key =
|
||||
if Feature.enabled?(:highlight_diffs_optimize_memory_usage, diffable.project)
|
||||
[OpenSSL::Digest::SHA256.hexdigest(options.join)]
|
||||
else
|
||||
options
|
||||
end
|
||||
|
||||
['highlighted-diff-files', diffable.cache_key, VERSION, *options_for_key].join(":")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def expiration_period
|
||||
if Feature.enabled?(:highlight_diffs_optimize_memory_usage, diffable.project)
|
||||
EXPIRATION
|
||||
else
|
||||
PREVIOUS_EXPIRATION_PERIOD
|
||||
end
|
||||
end
|
||||
|
||||
def set_highlighted_diff_lines(diff_file, content)
|
||||
diff_file.highlighted_diff_lines = content.map do |line|
|
||||
Gitlab::Diff::Line.safe_init_from_hash(line)
|
||||
|
@ -138,7 +153,7 @@ module Gitlab
|
|||
|
||||
# HSETs have to have their expiration date manually updated
|
||||
#
|
||||
redis.expire(key, EXPIRATION)
|
||||
redis.expire(key, expiration_period)
|
||||
end
|
||||
|
||||
record_memory_usage(fetch_memory_usage(redis, key))
|
||||
|
|
|
@ -19290,6 +19290,9 @@ msgstr ""
|
|||
msgid "HighlightBar|Time to SLA:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Historical release"
|
||||
msgstr ""
|
||||
|
||||
msgid "History"
|
||||
msgstr ""
|
||||
|
||||
|
@ -40061,6 +40064,9 @@ msgstr ""
|
|||
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
|
||||
msgstr ""
|
||||
|
||||
msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
|
||||
msgstr ""
|
||||
|
||||
msgid "This repository"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -164,6 +164,9 @@ describe('Package Files', () => {
|
|||
createComponent();
|
||||
|
||||
expect(findFirstActionMenu().exists()).toBe(true);
|
||||
expect(findFirstActionMenu().props('icon')).toBe('ellipsis_v');
|
||||
expect(findFirstActionMenu().props('textSrOnly')).toBe(true);
|
||||
expect(findFirstActionMenu().props('text')).toMatchInterpolatedText('More actions');
|
||||
});
|
||||
|
||||
describe('menu items', () => {
|
||||
|
|
|
@ -55,6 +55,7 @@ Object {
|
|||
"commitPath": "http://localhost/releases-namespace/releases-project/-/commit/b83d6e391c22777fca1ed3012fce84f633d7fed0",
|
||||
"descriptionHtml": "<p data-sourcepos=\\"1:1-1:23\\" dir=\\"auto\\">An okay release <gl-emoji title=\\"shrug\\" data-name=\\"shrug\\" data-unicode-version=\\"9.0\\">🤷</gl-emoji></p>",
|
||||
"evidences": Array [],
|
||||
"historicalRelease": false,
|
||||
"milestones": Array [],
|
||||
"name": "The second release",
|
||||
"releasedAt": 2019-01-10T00:00:00.000Z,
|
||||
|
@ -159,6 +160,7 @@ Object {
|
|||
"sha": "760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d",
|
||||
},
|
||||
],
|
||||
"historicalRelease": false,
|
||||
"milestones": Array [
|
||||
Object {
|
||||
"__typename": "Milestone",
|
||||
|
@ -373,6 +375,7 @@ Object {
|
|||
"sha": "760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d",
|
||||
},
|
||||
],
|
||||
"historicalRelease": false,
|
||||
"milestones": Array [
|
||||
Object {
|
||||
"__typename": "Milestone",
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { GlLink } from '@gitlab/ui';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import { GlLink, GlBadge } from '@gitlab/ui';
|
||||
import { merge } from 'lodash';
|
||||
import originalRelease from 'test_fixtures/api/releases/release.json';
|
||||
import setWindowLocation from 'helpers/set_window_location_helper';
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import { __ } from '~/locale';
|
||||
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
|
||||
import ReleaseBlockHeader from '~/releases/components/release_block_header.vue';
|
||||
import { BACK_URL_PARAM } from '~/releases/constants';
|
||||
|
@ -12,10 +13,11 @@ describe('Release block header', () => {
|
|||
let release;
|
||||
|
||||
const factory = (releaseUpdates = {}) => {
|
||||
wrapper = shallowMount(ReleaseBlockHeader, {
|
||||
wrapper = shallowMountExtended(ReleaseBlockHeader, {
|
||||
propsData: {
|
||||
release: merge({}, release, releaseUpdates),
|
||||
},
|
||||
stubs: { GlBadge },
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -30,6 +32,7 @@ describe('Release block header', () => {
|
|||
const findHeader = () => wrapper.find('h2');
|
||||
const findHeaderLink = () => findHeader().find(GlLink);
|
||||
const findEditButton = () => wrapper.find('.js-edit-button');
|
||||
const findBadge = () => wrapper.findComponent(GlBadge);
|
||||
|
||||
describe('when _links.self is provided', () => {
|
||||
beforeEach(() => {
|
||||
|
@ -84,4 +87,34 @@ describe('Release block header', () => {
|
|||
expect(findEditButton().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('upcoming release', () => {
|
||||
beforeEach(() => {
|
||||
factory({ upcomingRelease: true, historicalRelease: false });
|
||||
});
|
||||
|
||||
it('shows a badge that the release is upcoming', () => {
|
||||
const badge = findBadge();
|
||||
|
||||
expect(badge.text()).toBe(__('Upcoming Release'));
|
||||
expect(badge.props('variant')).toBe('warning');
|
||||
});
|
||||
});
|
||||
|
||||
describe('historical release', () => {
|
||||
beforeEach(() => {
|
||||
factory({ upcomingRelease: false, historicalRelease: true });
|
||||
});
|
||||
|
||||
it('shows a badge that the release is historical', () => {
|
||||
const badge = findBadge();
|
||||
|
||||
expect(badge.text()).toBe(__('Historical release'));
|
||||
expect(badge.attributes('title')).toBe(
|
||||
__(
|
||||
'This release was created with a date in the past. Evidence collection at the moment of the release is unavailable.',
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,16 +1,21 @@
|
|||
import { GlForm, GlFormInput } from '@gitlab/ui';
|
||||
import { nextTick } from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import { mockTracking } from 'helpers/tracking_helper';
|
||||
import { mountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { __ } from '~/locale';
|
||||
import WorkItemWeight from '~/work_items/components/work_item_weight.vue';
|
||||
import { TRACKING_CATEGORY_SHOW } from '~/work_items/constants';
|
||||
import localUpdateWorkItemMutation from '~/work_items/graphql/local_update_work_item.mutation.graphql';
|
||||
import { i18n, TRACKING_CATEGORY_SHOW } from '~/work_items/constants';
|
||||
import updateWorkItemMutation from '~/work_items/graphql/update_work_item.mutation.graphql';
|
||||
import { updateWorkItemMutationResponse } from 'jest/work_items/mock_data';
|
||||
|
||||
describe('WorkItemWeight component', () => {
|
||||
Vue.use(VueApollo);
|
||||
|
||||
let wrapper;
|
||||
|
||||
const mutateSpy = jest.fn();
|
||||
const workItemId = 'gid://gitlab/WorkItem/1';
|
||||
const workItemType = 'Task';
|
||||
|
||||
|
@ -22,8 +27,10 @@ describe('WorkItemWeight component', () => {
|
|||
hasIssueWeightsFeature = true,
|
||||
isEditing = false,
|
||||
weight,
|
||||
mutationHandler = jest.fn().mockResolvedValue(updateWorkItemMutationResponse),
|
||||
} = {}) => {
|
||||
wrapper = mountExtended(WorkItemWeight, {
|
||||
apolloProvider: createMockApollo([[updateWorkItemMutation, mutationHandler]]),
|
||||
propsData: {
|
||||
canUpdate,
|
||||
weight,
|
||||
|
@ -33,11 +40,6 @@ describe('WorkItemWeight component', () => {
|
|||
provide: {
|
||||
hasIssueWeightsFeature,
|
||||
},
|
||||
mocks: {
|
||||
$apollo: {
|
||||
mutate: mutateSpy,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (isEditing) {
|
||||
|
@ -131,23 +133,63 @@ describe('WorkItemWeight component', () => {
|
|||
});
|
||||
|
||||
describe('when blurred', () => {
|
||||
it('calls a mutation to update the weight', () => {
|
||||
const weight = 0;
|
||||
createComponent({ isEditing: true, weight });
|
||||
it('calls a mutation to update the weight when the input value is different', () => {
|
||||
const mutationSpy = jest.fn().mockResolvedValue(updateWorkItemMutationResponse);
|
||||
createComponent({ isEditing: true, weight: 0, mutationHandler: mutationSpy });
|
||||
|
||||
findInput().trigger('blur');
|
||||
findInput().vm.$emit('blur', { target: { value: 1 } });
|
||||
|
||||
expect(mutateSpy).toHaveBeenCalledWith({
|
||||
mutation: localUpdateWorkItemMutation,
|
||||
variables: {
|
||||
input: {
|
||||
id: workItemId,
|
||||
weight,
|
||||
expect(mutationSpy).toHaveBeenCalledWith({
|
||||
input: {
|
||||
id: workItemId,
|
||||
weightWidget: {
|
||||
weight: 1,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('does not call a mutation to update the weight when the input value is the same', () => {
|
||||
const mutationSpy = jest.fn().mockResolvedValue(updateWorkItemMutationResponse);
|
||||
createComponent({ isEditing: true, mutationHandler: mutationSpy });
|
||||
|
||||
findInput().trigger('blur');
|
||||
|
||||
expect(mutationSpy).not.toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it('emits an error when there is a GraphQL error', async () => {
|
||||
const response = {
|
||||
data: {
|
||||
workItemUpdate: {
|
||||
errors: ['Error!'],
|
||||
workItem: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
createComponent({
|
||||
isEditing: true,
|
||||
mutationHandler: jest.fn().mockResolvedValue(response),
|
||||
});
|
||||
|
||||
findInput().trigger('blur');
|
||||
await waitForPromises();
|
||||
|
||||
expect(wrapper.emitted('error')).toEqual([[i18n.updateError]]);
|
||||
});
|
||||
|
||||
it('emits an error when there is a network error', async () => {
|
||||
createComponent({
|
||||
isEditing: true,
|
||||
mutationHandler: jest.fn().mockRejectedValue(new Error()),
|
||||
});
|
||||
|
||||
findInput().trigger('blur');
|
||||
await waitForPromises();
|
||||
|
||||
expect(wrapper.emitted('error')).toEqual([[i18n.updateError]]);
|
||||
});
|
||||
|
||||
it('tracks updating the weight', () => {
|
||||
const trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
|
||||
createComponent();
|
||||
|
|
|
@ -77,6 +77,7 @@ export const updateWorkItemMutationResponse = {
|
|||
data: {
|
||||
workItemUpdate: {
|
||||
__typename: 'WorkItemUpdatePayload',
|
||||
errors: [],
|
||||
workItem: {
|
||||
__typename: 'WorkItem',
|
||||
id: 'gid://gitlab/WorkItem/1',
|
||||
|
@ -112,6 +113,7 @@ export const workItemResponseFactory = ({
|
|||
canUpdate = false,
|
||||
allowsMultipleAssignees = true,
|
||||
assigneesWidgetPresent = true,
|
||||
weightWidgetPresent = true,
|
||||
parent = null,
|
||||
} = {}) => ({
|
||||
data: {
|
||||
|
@ -148,6 +150,13 @@ export const workItemResponseFactory = ({
|
|||
},
|
||||
}
|
||||
: { type: 'MOCK TYPE' },
|
||||
weightWidgetPresent
|
||||
? {
|
||||
__typename: 'WorkItemWidgetWeight',
|
||||
type: 'WEIGHT',
|
||||
weight: 0,
|
||||
}
|
||||
: { type: 'MOCK TYPE' },
|
||||
{
|
||||
__typename: 'WorkItemWidgetHierarchy',
|
||||
type: 'HIERARCHY',
|
||||
|
|
|
@ -278,12 +278,14 @@ describe('WorkItemDetail component', () => {
|
|||
describe('weight widget', () => {
|
||||
describe('when work_items_mvc_2 feature flag is enabled', () => {
|
||||
describe.each`
|
||||
description | includeWidgets | exists
|
||||
${'when widget is returned from API'} | ${true} | ${true}
|
||||
${'when widget is not returned from API'} | ${false} | ${false}
|
||||
`('$description', ({ includeWidgets, exists }) => {
|
||||
it(`${includeWidgets ? 'renders' : 'does not render'} weight component`, async () => {
|
||||
createComponent({ includeWidgets, workItemsMvc2Enabled: true });
|
||||
description | weightWidgetPresent | exists
|
||||
${'when widget is returned from API'} | ${true} | ${true}
|
||||
${'when widget is not returned from API'} | ${false} | ${false}
|
||||
`('$description', ({ weightWidgetPresent, exists }) => {
|
||||
it(`${weightWidgetPresent ? 'renders' : 'does not render'} weight component`, async () => {
|
||||
const response = workItemResponseFactory({ weightWidgetPresent });
|
||||
const handler = jest.fn().mockResolvedValue(response);
|
||||
createComponent({ workItemsMvc2Enabled: true, handler });
|
||||
await waitForPromises();
|
||||
|
||||
expect(findWorkItemWeight().exists()).toBe(exists);
|
||||
|
@ -293,18 +295,28 @@ describe('WorkItemDetail component', () => {
|
|||
|
||||
describe('when work_items_mvc_2 feature flag is disabled', () => {
|
||||
describe.each`
|
||||
description | includeWidgets | exists
|
||||
${'when widget is returned from API'} | ${true} | ${false}
|
||||
${'when widget is not returned from API'} | ${false} | ${false}
|
||||
`('$description', ({ includeWidgets, exists }) => {
|
||||
it(`${includeWidgets ? 'renders' : 'does not render'} weight component`, async () => {
|
||||
createComponent({ includeWidgets, workItemsMvc2Enabled: false });
|
||||
description | weightWidgetPresent | exists
|
||||
${'when widget is returned from API'} | ${true} | ${false}
|
||||
${'when widget is not returned from API'} | ${false} | ${false}
|
||||
`('$description', ({ weightWidgetPresent, exists }) => {
|
||||
it(`${weightWidgetPresent ? 'renders' : 'does not render'} weight component`, async () => {
|
||||
createComponent({ weightWidgetPresent, workItemsMvc2Enabled: false });
|
||||
await waitForPromises();
|
||||
|
||||
expect(findWorkItemWeight().exists()).toBe(exists);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('shows an error message when it emits an `error` event', async () => {
|
||||
createComponent({ workItemsMvc2Enabled: true });
|
||||
await waitForPromises();
|
||||
|
||||
findWorkItemWeight().vm.$emit('error', i18n.updateError);
|
||||
await waitForPromises();
|
||||
|
||||
expect(findAlert().text()).toBe(i18n.updateError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('work item information', () => {
|
||||
|
|
|
@ -115,6 +115,10 @@ RSpec.describe Gitlab::Diff::HighlightCache, :clean_gitlab_redis_cache do
|
|||
.once
|
||||
.and_call_original
|
||||
|
||||
Gitlab::Redis::Cache.with do |redis|
|
||||
expect(redis).to receive(:expire).with(cache.key, described_class::EXPIRATION)
|
||||
end
|
||||
|
||||
2.times { cache.write_if_empty }
|
||||
end
|
||||
|
||||
|
@ -123,6 +127,20 @@ RSpec.describe Gitlab::Diff::HighlightCache, :clean_gitlab_redis_cache do
|
|||
|
||||
cache.write_if_empty
|
||||
end
|
||||
|
||||
context 'when highlight_diffs_optimize_memory_usage is disabled' do
|
||||
before do
|
||||
stub_feature_flags(highlight_diffs_optimize_memory_usage: false)
|
||||
end
|
||||
|
||||
it 'sets the previous expiration period' do
|
||||
Gitlab::Redis::Cache.with do |redis|
|
||||
expect(redis).to receive(:expire).with(cache.key, described_class::PREVIOUS_EXPIRATION_PERIOD)
|
||||
end
|
||||
|
||||
cache.write_if_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#write_if_empty' do
|
||||
|
@ -259,8 +277,12 @@ RSpec.describe Gitlab::Diff::HighlightCache, :clean_gitlab_redis_cache do
|
|||
describe '#key' do
|
||||
subject { cache.key }
|
||||
|
||||
def options_hash(options_array)
|
||||
OpenSSL::Digest::SHA256.hexdigest(options_array.join)
|
||||
end
|
||||
|
||||
it 'returns cache key' do
|
||||
is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:true:true")
|
||||
is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{options_hash([cache.diff_options, true, true])}")
|
||||
end
|
||||
|
||||
context 'when the `use_marker_ranges` feature flag is disabled' do
|
||||
|
@ -269,7 +291,7 @@ RSpec.describe Gitlab::Diff::HighlightCache, :clean_gitlab_redis_cache do
|
|||
end
|
||||
|
||||
it 'returns the original version of the cache' do
|
||||
is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:false:true")
|
||||
is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{options_hash([cache.diff_options, false, true])}")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -279,7 +301,17 @@ RSpec.describe Gitlab::Diff::HighlightCache, :clean_gitlab_redis_cache do
|
|||
end
|
||||
|
||||
it 'returns the original version of the cache' do
|
||||
is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:true:false")
|
||||
is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{options_hash([cache.diff_options, true, false])}")
|
||||
end
|
||||
end
|
||||
|
||||
context 'when highlight_diffs_optimize_memory_usage is disabled' do
|
||||
before do
|
||||
stub_feature_flags(highlight_diffs_optimize_memory_usage: false)
|
||||
end
|
||||
|
||||
it 'uses the options hash as a part of the cache key' do
|
||||
is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:true:true")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4660,6 +4660,37 @@ RSpec.describe MergeRequest, factory_default: :keep do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#in_locked_state' do
|
||||
let(:merge_request) { create(:merge_request, :opened) }
|
||||
|
||||
context 'when the merge request does not change state' do
|
||||
it 'returns to previous state and has no errors on the object' do
|
||||
expect(merge_request.opened?).to eq(true)
|
||||
|
||||
merge_request.in_locked_state do
|
||||
expect(merge_request.locked?).to eq(true)
|
||||
end
|
||||
|
||||
expect(merge_request.opened?).to eq(true)
|
||||
expect(merge_request.errors).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the merge request is merged while locked' do
|
||||
it 'becomes merged and has no errors on the object' do
|
||||
expect(merge_request.opened?).to eq(true)
|
||||
|
||||
merge_request.in_locked_state do
|
||||
expect(merge_request.locked?).to eq(true)
|
||||
merge_request.mark_as_merged!
|
||||
end
|
||||
|
||||
expect(merge_request.merged?).to eq(true)
|
||||
expect(merge_request.errors).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#cleanup_refs' do
|
||||
subject { merge_request.cleanup_refs(only: only) }
|
||||
|
||||
|
|
|
@ -2482,11 +2482,28 @@ RSpec.describe API::MergeRequests do
|
|||
let(:pipeline) { create(:ci_pipeline, project: project) }
|
||||
|
||||
it "returns merge_request in case of success" do
|
||||
put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user)
|
||||
expect { put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user) }
|
||||
.to change { merge_request.reload.merged? }
|
||||
.from(false)
|
||||
.to(true)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
|
||||
context 'when the merge request fails to merge' do
|
||||
it 'returns 422' do
|
||||
expect_next_instance_of(::MergeRequests::MergeService) do |service|
|
||||
expect(service).to receive(:execute)
|
||||
end
|
||||
|
||||
expect { put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user) }
|
||||
.not_to change { merge_request.reload.merged? }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:unprocessable_entity)
|
||||
expect(json_response['message']).to eq("Failed to merge branch")
|
||||
end
|
||||
end
|
||||
|
||||
context 'when change_response_code_merge_status is enabled' do
|
||||
it "returns 422 if branch can't be merged" do
|
||||
allow_next_found_instance_of(MergeRequest) do |merge_request|
|
||||
|
|
Loading…
Reference in New Issue