diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-07-26 18:10:26 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-07-26 18:10:26 +0300 |
commit | 60a260df4186ab0fe08352d1eb957b34ebdeb7c2 (patch) | |
tree | 5c1f44c0cb9c992cd0e1c7d3aa0b241359438314 | |
parent | ee0b7522d90ace2053f1d8dfcdf6b01d50179ed1 (diff) |
Add latest changes from gitlab-org/gitlab@master
66 files changed, 383 insertions, 1155 deletions
@@ -536,7 +536,7 @@ gem 'valid_email', '~> 0.1' # JSON gem 'json', '~> 2.5.1' gem 'json_schemer', '~> 0.2.18' -gem 'oj', '~> 3.13.17' +gem 'oj', '~> 3.13.18' gem 'multi_json', '~> 1.14.1' gem 'yajl-ruby', '~> 1.4.1', require: 'yajl' diff --git a/Gemfile.lock b/Gemfile.lock index d8c3b881ac2..c32c8a6d2a7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -869,7 +869,7 @@ GEM plist (~> 3.1) train-core wmi-lite (~> 1.0) - oj (3.13.17) + oj (3.13.18) omniauth (1.9.1) hashie (>= 3.4.6) rack (>= 1.6.2, < 3) @@ -1637,7 +1637,7 @@ DEPENDENCIES oauth2 (~> 2.0) octokit (~> 4.15) ohai (~> 16.10) - oj (~> 3.13.17) + oj (~> 3.13.18) omniauth (~> 1.8) omniauth-alicloud (~> 1.0.1) omniauth-atlassian-oauth2 (~> 0.2.0) diff --git a/app/assets/javascripts/notes/components/note_actions.vue b/app/assets/javascripts/notes/components/note_actions.vue index 10e3f57a56d..c7f293a219a 100644 --- a/app/assets/javascripts/notes/components/note_actions.vue +++ b/app/assets/javascripts/notes/components/note_actions.vue @@ -170,7 +170,7 @@ export default { return this.targetType === 'issue'; }, canAssign() { - return this.getNoteableData.current_user?.can_update && this.isIssue; + return this.getNoteableData.current_user?.can_set_issue_metadata && this.isIssue; }, displayAuthorBadgeText() { return sprintf(__('This user is the author of this %{noteable}.'), { diff --git a/app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue b/app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue index 437d035fbf5..266f1fb594b 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue @@ -52,31 +52,20 @@ export default { return n__('%d commit', '%d commits', this.isSquashEnabled ? 1 : this.commitsCount); }, message() { - if (this.glFeatures.restructuredMrWidget) { - if (this.state === 'closed') { - return s__('mrWidgetCommitsAdded|The changes were not merged into %{targetBranch}.'); - } else if (this.isMerged) { - return s__( - 'mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}.', - ); - } - - return this.isFastForwardEnabled - ? s__('mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}.') - : s__( - 'mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}%{squashedCommits}.', - ); + if (this.state === 'closed') { + return s__('mrWidgetCommitsAdded|The changes were not merged into %{targetBranch}.'); + } else if (this.isMerged) { + return s__( + 'mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}.', + ); } return this.isFastForwardEnabled - ? s__('mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}.') + ? s__('mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}.') : s__( - 'mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}.', + 'mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}%{squashedCommits}.', ); }, - textDecorativeComponent() { - return this.glFeatures.restructuredMrWidget ? 'span' : 'strong'; - }, squashCommitMessage() { if (this.isMerged) { return s__('mergedCommitsAdded|(commits were squashed)'); @@ -93,25 +82,19 @@ export default { <span> <gl-sprintf :message="message"> <template #commitCount> - <component :is="textDecorativeComponent" class="commits-count-message">{{ - commitsCountMessage - }}</component> + <span class="commits-count-message">{{ commitsCountMessage }}</span> </template> <template #mergeCommitCount> - <component :is="textDecorativeComponent">{{ $options.mergeCommitCount }}</component> + <span>{{ $options.mergeCommitCount }}</span> </template> <template #targetBranch> <span class="label-branch">{{ targetBranchEscaped }}</span> </template> <template #squashedCommits> - <template v-if="glFeatures.restructuredMrWidget && isSquashEnabled"> - {{ squashCommitMessage }}</template - ></template - > + <template v-if="isSquashEnabled"> {{ squashCommitMessage }}</template> + </template> <template #mergeCommitSha> - <template v-if="glFeatures.restructuredMrWidget" - ><span class="label-branch">{{ mergeCommitSha }}</span></template - > + <span class="label-branch">{{ mergeCommitSha }}</span> </template> </gl-sprintf> </span> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue index 913aa0e1e34..94a1b805b99 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue @@ -1,7 +1,6 @@ <script> -import { GlSafeHtmlDirective as SafeHtml, GlLink, GlSprintf } from '@gitlab/ui'; +import { GlSafeHtmlDirective as SafeHtml, GlLink } from '@gitlab/ui'; import { s__, n__ } from '~/locale'; -import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; export default { name: 'MRWidgetRelatedLinks', @@ -10,9 +9,7 @@ export default { }, components: { GlLink, - GlSprintf, }, - mixins: [glFeatureFlagMixin()], props: { relatedLinks: { type: Object, @@ -67,42 +64,21 @@ export default { </script> <template> <section> - <p - v-if="relatedLinks.closing" - :class="{ 'gl-display-inline gl-m-0': glFeatures.restructuredMrWidget }" - > + <p v-if="relatedLinks.closing" class="gl-display-inline gl-m-0"> {{ closesText }} <span v-safe-html="relatedLinks.closing"></span> </p> - <p - v-if="relatedLinks.mentioned" - :class="{ 'gl-display-inline gl-m-0': glFeatures.restructuredMrWidget }" - > - <span v-if="relatedLinks.closing && glFeatures.restructuredMrWidget">·</span> + <p v-if="relatedLinks.mentioned" class="gl-display-inline gl-m-0"> + <span v-if="relatedLinks.closing">·</span> {{ n__('mrWidget|Mentions issue', 'mrWidget|Mentions issues', relatedLinks.mentionedCount) }} <span v-safe-html="relatedLinks.mentioned"></span> </p> - <p - v-if="shouldShowAssignToMeLink" - :class="{ 'gl-display-inline gl-m-0': glFeatures.restructuredMrWidget }" - > + <p v-if="shouldShowAssignToMeLink" class="gl-display-inline gl-m-0"> <span> <gl-link rel="nofollow" data-method="post" :href="relatedLinks.assignToMe">{{ assignIssueText }}</gl-link> </span> </p> - <div - v-if="divergedCommitsCount > 0 && !glFeatures.restructuredMrWidget" - class="diverged-commits-count" - > - <gl-sprintf :message="s__('mrWidget|The source branch is %{link} the target branch')"> - <template #link> - <gl-link :href="targetBranchPath">{{ - n__('%d commit behind', '%d commits behind', divergedCommitsCount) - }}</gl-link> - </template> - </gl-sprintf> - </div> </section> </template> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue index 7ff1eb6e73a..5b8acb4ebf8 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue @@ -1,25 +1,17 @@ <script> -import { GlButton, GlLoadingIcon } from '@gitlab/ui'; -import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; +import { GlLoadingIcon } from '@gitlab/ui'; import ciIcon from '~/vue_shared/components/ci_icon.vue'; export default { components: { ciIcon, - GlButton, GlLoadingIcon, }, - mixins: [glFeatureFlagMixin()], props: { status: { type: String, required: true, }, - showDisabledButton: { - type: Boolean, - required: false, - default: false, - }, }, computed: { isLoading() { @@ -42,15 +34,5 @@ export default { </div> <ci-icon v-else :status="statusObj" :size="24" /> </div> - - <gl-button - v-if="!glFeatures.restructuredMrWidget && showDisabledButton" - category="primary" - variant="confirm" - data-testid="disabled-merge-button" - :disabled="true" - > - {{ s__('mrWidget|Merge') }} - </gl-button> </div> </template> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue index 18761d04c2e..515a7cf51a1 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue @@ -1,8 +1,5 @@ <script> -import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; - export default { - mixins: [glFeatureFlagMixin()], props: { value: { type: String, @@ -23,10 +20,7 @@ export default { <template> <li> <div class="commit-message-editor"> - <div - :class="{ 'gl-mb-3': glFeatures.restructuredMrWidget }" - class="d-flex flex-wrap align-items-center justify-content-between" - > + <div class="d-flex flex-wrap align-items-center justify-content-between gl-mb-3"> <label class="col-form-label" :for="inputId"> <strong>{{ label }}</strong> </label> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue index 071920856a8..f74826f95d3 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue @@ -1,5 +1,4 @@ <script> -import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import statusIcon from '../mr_widget_status_icon.vue'; export default { @@ -7,7 +6,6 @@ export default { components: { statusIcon, }, - mixins: [glFeatureFlagMixin()], }; </script> <template> @@ -16,7 +14,7 @@ export default { <status-icon status="warning" show-disabled-button /> </div> <div class="media-body"> - <span :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" class="bold"> + <span class="gl-ml-0! gl-text-body! bold"> {{ s__('mrWidget|Merge unavailable: merge requests are read-only on archived projects.') }} </span> </div> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue index aabbeac564a..63bd8f3d8dc 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue @@ -3,7 +3,6 @@ import { GlSkeletonLoader, GlIcon, GlButton, GlSprintf } from '@gitlab/ui'; import autoMergeMixin from 'ee_else_ce/vue_merge_request_widget/mixins/auto_merge'; import autoMergeEnabledQuery from 'ee_else_ce/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql'; import createFlash from '~/flash'; -import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import { __ } from '~/locale'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { AUTO_MERGE_STRATEGIES } from '../../constants'; @@ -78,19 +77,6 @@ export default { autoMergeStrategy() { return (this.glFeatures.mergeRequestWidgetGraphql ? this.state : this.mr).autoMergeStrategy; }, - canRemoveSourceBranch() { - const { currentUserId } = this.mr; - const mergeUserId = this.glFeatures.mergeRequestWidgetGraphql - ? getIdFromGraphQLId(this.state.mergeUser?.id) - : this.mr.mergeUserId; - const canRemoveSourceBranch = this.glFeatures.mergeRequestWidgetGraphql - ? this.state.userPermissions.removeSourceBranch - : this.mr.canRemoveSourceBranch; - - return ( - !this.shouldRemoveSourceBranch && canRemoveSourceBranch && mergeUserId === currentUserId - ); - }, }, methods: { cancelAutomaticMerge() { @@ -175,24 +161,6 @@ export default { {{ cancelButtonText }} </gl-button> </h4> - <section v-if="!glFeatures.restructuredMrWidget" class="mr-info-list"> - <p v-if="shouldRemoveSourceBranch"> - {{ s__('mrWidget|Deletes the source branch') }} - </p> - <p v-else class="gl-display-flex"> - <span class="gl-mr-3">{{ s__('mrWidget|Does not delete the source branch') }}</span> - <gl-button - v-if="canRemoveSourceBranch" - :loading="isRemovingSourceBranch" - size="small" - class="js-remove-source-branch" - data-testid="removeSourceBranchButton" - @click="removeSourceBranch" - > - {{ s__('mrWidget|Delete source branch') }} - </gl-button> - </p> - </section> </div> </template> </div> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue index fd42fa0421f..e2d87d8d536 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue @@ -1,5 +1,4 @@ <script> -import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import statusIcon from '../mr_widget_status_icon.vue'; export default { @@ -7,14 +6,13 @@ export default { components: { statusIcon, }, - mixins: [glFeatureFlagMixin()], }; </script> <template> <div class="mr-widget-body media"> <status-icon :show-disabled-button="true" status="loading" /> <div class="media-body space-children"> - <span :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" class="bold"> + <span class="gl-ml-0! gl-text-body! bold"> {{ s__('mrWidget|Checking if merge request can be merged…') }} </span> </div> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue index d50e52f5ac1..61f7d26f51e 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue @@ -1,5 +1,4 @@ <script> -import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import MrWidgetAuthorTime from '../mr_widget_author_time.vue'; import statusIcon from '../mr_widget_status_icon.vue'; @@ -9,7 +8,6 @@ export default { MrWidgetAuthorTime, statusIcon, }, - mixins: [glFeatureFlagMixin()], props: { /* TODO: This is providing all store and service down when it only needs metrics and targetBranch */ @@ -30,13 +28,6 @@ export default { :date-title="mr.metrics.closedAt" :date-readable="mr.metrics.readableClosedAt" /> - - <section v-if="!glFeatures.restructuredMrWidget" class="mr-info-list"> - <p> - {{ s__('mrWidget|The changes were not merged into') }} - <a :href="mr.targetBranchPath" class="label-branch"> {{ mr.targetBranch }} </a> - </p> - </section> </div> </div> </template> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue index def30dacf8a..7652d7049f2 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue @@ -97,18 +97,14 @@ export default { </gl-skeleton-loader> </div> <div v-else class="media-body space-children gl-display-flex gl-align-items-center"> - <span - v-if="shouldBeRebased" - :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" - class="bold" - > + <span v-if="shouldBeRebased" class="gl-ml-0! gl-text-body! bold"> {{ s__(`mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally.`) }} </span> <template v-else> - <span :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" class="bold"> + <span class="gl-ml-0! gl-text-body! bold"> {{ s__('mrWidget|Merge blocked: merge conflicts must be resolved.') }} <span v-if="!canMerge"> {{ @@ -121,14 +117,14 @@ export default { <gl-button v-if="showResolveButton" :href="mr.conflictResolutionPath" - :size="glFeatures.restructuredMrWidget ? 'small' : 'medium'" + size="small" data-testid="resolve-conflicts-button" > {{ s__('mrWidget|Resolve conflicts') }} </gl-button> <gl-button v-if="canMerge" - :size="glFeatures.restructuredMrWidget ? 'small' : 'medium'" + size="small" data-testid="merge-locally-button" class="js-check-out-modal-trigger" > diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue index bf036f562ed..19df346759f 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue @@ -1,13 +1,10 @@ <script> -/* eslint-disable @gitlab/vue-require-i18n-strings */ -import { GlLoadingIcon, GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui'; -import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; +import { GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui'; import api from '~/api'; import createFlash from '~/flash'; import { s__, __ } from '~/locale'; import { OPEN_REVERT_MODAL, OPEN_CHERRY_PICK_MODAL } from '~/projects/commit/constants'; import modalEventHub from '~/projects/commit/event_hub'; -import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; import eventHub from '../../event_hub'; import MrWidgetAuthorTime from '../mr_widget_author_time.vue'; @@ -19,11 +16,8 @@ export default { components: { MrWidgetAuthorTime, GlIcon, - ClipboardButton, - GlLoadingIcon, GlButton, }, - mixins: [glFeatureFlagMixin()], props: { mr: { type: Object, @@ -183,41 +177,6 @@ export default { {{ s__('mrWidget|Delete source branch') }} </gl-button> </div> - <section - v-if="!glFeatures.restructuredMrWidget" - class="mr-info-list" - data-qa-selector="merged_status_content" - > - <p> - {{ s__('mrWidget|The changes were merged into') }} - <span class="label-branch"> - <a :href="mr.targetBranchPath">{{ mr.targetBranch }}</a> - </span> - <template v-if="mr.mergeCommitSha"> - with - <a - :href="mr.mergeCommitPath" - class="commit-sha js-mr-merged-commit-sha" - v-text="mr.shortMergeCommitSha" - > - </a> - <clipboard-button - :title="__('Copy commit SHA')" - :text="mr.mergeCommitSha" - css-class="js-mr-merged-copy-sha" - category="tertiary" - size="small" - /> - </template> - </p> - <p v-if="mr.sourceBranchRemoved"> - {{ s__('mrWidget|The source branch has been deleted') }} - </p> - <p v-if="shouldShowSourceBranchRemoving"> - <gl-loading-icon size="sm" :inline="true" /> - <span> {{ s__('mrWidget|The source branch is being deleted') }} </span> - </p> - </section> </div> </div> </template> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue index b86ab69af3f..c7574a41bb8 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue @@ -1,6 +1,5 @@ <script> import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests'; -import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import simplePoll from '~/lib/utils/simple_poll'; import MergeRequest from '~/merge_request'; import eventHub from '../../event_hub'; @@ -15,7 +14,6 @@ export default { components: { statusIcon, }, - mixins: [glFeatureFlagMixin()], props: { mr: { type: Object, @@ -90,14 +88,6 @@ export default { {{ mergeStatus.message }} <gl-emoji :data-name="mergeStatus.emoji" /> </h4> - <section v-if="!glFeatures.restructuredMrWidget" class="mr-info-list"> - <p> - {{ s__('mrWidget|Merges changes into') }} - <span class="label-branch"> - <a :href="mr.targetBranchPath">{{ mr.targetBranch }}</a> - </span> - </p> - </section> </div> </div> </template> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue index cadbd9c28a9..659d12d1160 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue @@ -74,13 +74,7 @@ export default { <status-icon :show-disabled-button="true" status="warning" /> <div class="media-body space-children"> - <span - :class="{ - 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget, - }" - class="bold js-branch-text" - data-testid="widget-content" - > + <span class="gl-ml-0! gl-text-body! bold js-branch-text" data-testid="widget-content"> <gl-sprintf :message="warning"> <template #code="{ content }"> <code>{{ content }}</code> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue index 34c5a2ff2c8..e99ee59b877 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue @@ -14,7 +14,7 @@ export default { <div class="mr-widget-body media"> <status-icon :show-disabled-button="true" status="warning" /> <div class="media-body space-children"> - <span :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" class="bold"> + <span class="gl-ml-0! gl-text-body! bold"> {{ s__( `mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue.`, diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue index 59767eb2e6e..0880fd81500 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue @@ -161,15 +161,13 @@ export default { <div class="rebase-state-find-class-convention media media-body space-children"> <span v-if="rebaseInProgress || isMakingRequest" - :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" - class="gl-font-weight-bold" + class="gl-ml-0! gl-text-body! gl-font-weight-bold" data-testid="rebase-message" >{{ __('Rebase in progress') }}</span > <span v-if="!rebaseInProgress && !canPushToSourceBranch" - :class="{ 'gl-text-body!': glFeatures.restructuredMrWidget }" - class="gl-font-weight-bold gl-ml-0!" + class="gl-text-body! gl-font-weight-bold gl-ml-0!" data-testid="rebase-message" >{{ fastForwardMergeText }}</span > @@ -177,30 +175,9 @@ export default { v-if="!rebaseInProgress && canPushToSourceBranch && !isMakingRequest" class="accept-merge-holder clearfix js-toggle-container accept-action media space-children gl-align-items-center" > - <gl-button - v-if="!glFeatures.restructuredMrWidget" - :loading="isMakingRequest" - variant="confirm" - data-qa-selector="mr_rebase_button" - data-testid="standard-rebase-button" - @click="rebase" - > - {{ __('Rebase') }} - </gl-button> - <gl-button - v-if="!glFeatures.restructuredMrWidget && showRebaseWithoutCi" - :loading="isMakingRequest" - variant="confirm" - category="secondary" - data-testid="rebase-without-ci-button" - @click="rebaseWithoutCi" - > - {{ __('Rebase without pipeline') }} - </gl-button> <span v-if="!rebasingError" - :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" - class="gl-font-weight-bold" + class="gl-ml-0! gl-text-body! gl-font-weight-bold" data-testid="rebase-message" data-qa-selector="no_fast_forward_message_content" >{{ @@ -211,18 +188,18 @@ export default { rebasingError }}</span> <gl-button - v-if="glFeatures.restructuredMrWidget" :loading="isMakingRequest" variant="confirm" size="small" data-qa-selector="mr_rebase_button" + data-testid="standard-rebase-button" class="gl-ml-3!" @click="rebase" > {{ __('Rebase') }} </gl-button> <gl-button - v-if="glFeatures.restructuredMrWidget && showRebaseWithoutCi" + v-if="showRebaseWithoutCi" :loading="isMakingRequest" variant="confirm" size="small" diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue index d204befef58..d507e5f232b 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue @@ -1,7 +1,6 @@ <script> import { GlLink, GlSprintf } from '@gitlab/ui'; import { helpPagePath } from '~/helpers/help_page_helper'; -import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { s__ } from '~/locale'; import statusIcon from '../mr_widget_status_icon.vue'; @@ -12,7 +11,6 @@ export default { GlSprintf, statusIcon, }, - mixins: [glFeatureFlagMixin()], computed: { troubleshootingDocsPath() { return helpPagePath('ci/troubleshooting', { anchor: 'merge-request-status-messages' }); @@ -30,7 +28,7 @@ export default { <div class="mr-widget-body media"> <status-icon :show-disabled-button="true" status="warning" /> <div class="media-body space-children"> - <span :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" class="bold"> + <span class="gl-ml-0! gl-text-body! bold"> <gl-sprintf :message="$options.i18n.failedMessage"> <template #link="{ content }"> <gl-link :href="troubleshootingDocsPath" target="_blank"> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue index cf482410bef..884fc666276 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue @@ -31,12 +31,10 @@ import { import eventHub from '../../event_hub'; import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables'; import MergeRequestStore from '../../stores/mr_widget_store'; -import statusIcon from '../mr_widget_status_icon.vue'; import AddedCommitMessage from '../added_commit_message.vue'; import RelatedLinks from '../mr_widget_related_links.vue'; import CommitEdit from './commit_edit.vue'; import CommitMessageDropdown from './commit_message_dropdown.vue'; -import CommitsHeader from './commits_header.vue'; import SquashBeforeMerge from './squash_before_merge.vue'; import MergeFailedPipelineConfirmationDialog from './merge_failed_pipeline_confirmation_dialog.vue'; @@ -96,9 +94,7 @@ export default { }, }, components: { - statusIcon, SquashBeforeMerge, - CommitsHeader, CommitEdit, CommitMessageDropdown, GlIcon, @@ -320,34 +316,24 @@ export default { showDangerMessageForMergeTrain() { return this.preferredAutoMergeStrategy === MT_MERGE_STRATEGY && this.isPipelineFailed; }, - restructuredWidgetShowMergeButtons() { - if (this.glFeatures.restructuredMrWidget) { - return ( - (this.isMergeAllowed || this.isAutoMergeAvailable) && - this.state.userPermissions.canMerge && - !this.mr.mergeOngoing && - !this.mr.autoMergeEnabled - ); - } - - return true; + shouldShowMergeControls() { + return ( + (this.isMergeAllowed || this.isAutoMergeAvailable) && + (this.stateData.userPermissions?.canMerge || this.mr.canMerge) && + !this.mr.mergeOngoing && + !this.mr.autoMergeEnabled + ); }, sourceBranchDeletedText() { - if (this.glFeatures.restructuredMrWidget) { - if (this.removeSourceBranch) { - return this.mr.state === 'merged' - ? __('Deleted the source branch.') - : __('Source branch will be deleted.'); - } - + if (this.removeSourceBranch) { return this.mr.state === 'merged' - ? __('Did not delete the source branch.') - : __('Source branch will not be deleted.'); + ? __('Deleted the source branch.') + : __('Source branch will be deleted.'); } - return this.removeSourceBranch - ? __('Deletes the source branch.') - : __('Does not delete the source branch.'); + return this.mr.state === 'merged' + ? __('Did not delete the source branch.') + : __('Source branch will not be deleted.'); }, }, mounted() { @@ -525,10 +511,7 @@ export default { <template> <div data-testid="ready_to_merge_state" - :class="{ - 'gl-border-t-1 gl-border-t-solid gl-border-gray-100 gl-bg-gray-10 gl-pl-7 gl-rounded-bottom-left-base gl-rounded-bottom-right-base': - glFeatures.restructuredMrWidget, - }" + class="gl-border-t-1 gl-border-t-solid gl-border-gray-100 gl-bg-gray-10 gl-pl-7 gl-rounded-bottom-left-base gl-rounded-bottom-right-base" > <div v-if="loading" class="mr-widget-body"> <div class="gl-w-full mr-ready-to-merge-loader"> @@ -541,16 +524,10 @@ export default { </div> </div> <template v-else> - <div - class="mr-widget-body media" - :class="{ - 'mr-widget-body-line-height-1': glFeatures.restructuredMrWidget, - }" - > - <status-icon v-if="!glFeatures.restructuredMrWidget" :status="iconClass" /> + <div class="mr-widget-body media mr-widget-body-line-height-1"> <div class="media-body"> <div class="mr-widget-body-controls gl-display-flex gl-align-items-center gl-flex-wrap"> - <gl-button-group v-if="restructuredWidgetShowMergeButtons" class="gl-align-self-start"> + <gl-button-group v-if="shouldShowMergeControls" class="gl-align-self-start"> <gl-button size="medium" category="primary" @@ -603,19 +580,14 @@ export default { <merge-train-helper-icon v-if="shouldRenderMergeTrainHelperIcon" class="gl-mx-3" /> <div v-if="shouldShowMergeControls" - :class="{ 'gl-w-full gl-order-n1 gl-mb-5': glFeatures.restructuredMrWidget }" - class="gl-display-flex gl-align-items-center gl-flex-wrap" + class="gl-display-flex gl-align-items-center gl-flex-wrap gl-w-full gl-order-n1 gl-mb-5" > <gl-form-checkbox v-if="canRemoveSourceBranch" id="remove-source-branch-input" v-model="removeSourceBranch" :disabled="isRemoveSourceBranchButtonDisabled" - :class="{ - 'gl-mx-3': !glFeatures.restructuredMrWidget, - 'gl-mr-5': glFeatures.restructuredMrWidget, - }" - class="js-remove-source-branch-checkbox gl-display-flex gl-align-items-center" + class="js-remove-source-branch-checkbox gl-display-flex gl-align-items-center gl-mr-5" > {{ __('Delete source branch') }} </gl-form-checkbox> @@ -626,16 +598,11 @@ export default { v-model="squashBeforeMerge" :help-path="mr.squashBeforeMergeHelpPath" :is-disabled="isSquashReadOnly" - :class="{ - 'gl-mx-3': !glFeatures.restructuredMrWidget, - 'gl-mr-5': glFeatures.restructuredMrWidget, - }" + class="gl-mr-5" /> <gl-form-checkbox - v-if=" - glFeatures.restructuredMrWidget && (shouldShowSquashEdit || shouldShowMergeEdit) - " + v-if="shouldShowSquashEdit || shouldShowMergeEdit" v-model="editCommitMessage" data-testid="widget_edit_commit_message" class="gl-display-flex gl-align-items-center" @@ -644,198 +611,113 @@ export default { </gl-form-checkbox> </div> <div - v-else-if="!glFeatures.restructuredMrWidget" - class="bold js-resolve-mr-widget-items-message gl-ml-3" + v-if="editCommitMessage" + class="gl-w-full gl-order-n1" + data-testid="edit_commit_message" > - <div - v-if="hasPipelineMustSucceedConflict" - class="gl-display-flex gl-align-items-center" - data-testid="pipeline-succeed-conflict" - > - <gl-sprintf :message="pipelineMustSucceedConflictText" /> - <gl-link - :href="mr.pipelineMustSucceedDocsPath" - target="_blank" - class="gl-display-flex gl-ml-2" + <ul class="border-top commits-list flex-list gl-list-style-none gl-p-0 gl-pt-4"> + <commit-edit + v-if="shouldShowSquashEdit" + :value="squashCommitMessage" + :label="__('Squash commit message')" + input-id="squash-message-edit" + class="gl-m-0! gl-p-0!" + @input="setSquashCommitMessage" > - <gl-icon name="question" /> - </gl-link> - </div> - <gl-sprintf v-else :message="mergeDisabledText" /> + <template #header> + <commit-message-dropdown :commits="commits" @input="setSquashCommitMessage" /> + </template> + </commit-edit> + <commit-edit + v-if="shouldShowMergeEdit" + :value="commitMessage" + :label="__('Merge commit message')" + input-id="merge-message-edit" + class="gl-m-0! gl-p-0!" + @input="setCommitMessage" + /> + <li class="gl-m-0! gl-p-0!"> + <p class="form-text text-muted"> + <gl-sprintf :message="commitTemplateHintText"> + <template #link="{ content }"> + <gl-link :href="commitTemplateHelpPage" class="inline-link" target="_blank"> + {{ content }} + </gl-link> + </template> + </gl-sprintf> + </p> + </li> + </ul> </div> - <template v-if="glFeatures.restructuredMrWidget"> - <div - v-if="editCommitMessage" - class="gl-w-full gl-order-n1" - data-testid="edit_commit_message" - > - <ul - :class="{ - 'content-list': !glFeatures.restructuredMrWidget, - 'gl-list-style-none gl-p-0 gl-pt-4': glFeatures.restructuredMrWidget, - }" - class="border-top commits-list flex-list" - > - <commit-edit - v-if="shouldShowSquashEdit" - :value="squashCommitMessage" - :label="__('Squash commit message')" - input-id="squash-message-edit" - class="gl-m-0! gl-p-0!" - @input="setSquashCommitMessage" + <div + v-if="!shouldShowMergeControls" + class="gl-w-full gl-order-n1 gl-text-gray-500" + data-qa-selector="merged_status_content" + > + <strong v-if="mr.state !== 'closed'"> + {{ __('Merge details') }} + </strong> + <ul class="gl-pl-4 gl-m-0"> + <li v-if="mr.divergedCommitsCount > 0" class="gl-line-height-normal"> + <gl-sprintf + :message="s__('mrWidget|The source branch is %{link} the target branch')" > - <template #header> - <commit-message-dropdown :commits="commits" @input="setSquashCommitMessage" /> + <template #link> + <gl-link :href="mr.targetBranchPath">{{ + n__('%d commit behind', '%d commits behind', mr.divergedCommitsCount) + }}</gl-link> </template> - </commit-edit> - <commit-edit - v-if="shouldShowMergeEdit" - :value="commitMessage" - :label="__('Merge commit message')" - input-id="merge-message-edit" - class="gl-m-0! gl-p-0!" - @input="setCommitMessage" + </gl-sprintf> + </li> + <li class="gl-line-height-normal"> + <added-commit-message + :state="mr.state" + :merge-commit-sha="mr.shortMergeCommitSha" + :is-squash-enabled="squashBeforeMerge" + :is-fast-forward-enabled="!shouldShowMergeEdit" + :commits-count="commitsCount" + :target-branch="stateData.targetBranch" /> - <li class="gl-m-0! gl-p-0!"> - <p class="form-text text-muted"> - <gl-sprintf :message="commitTemplateHintText"> - <template #link="{ content }"> - <gl-link - :href="commitTemplateHelpPage" - class="inline-link" - target="_blank" - > - {{ content }} - </gl-link> - </template> - </gl-sprintf> - </p> - </li> - </ul> - </div> - <div - v-if="!restructuredWidgetShowMergeButtons" - class="gl-w-full gl-order-n1 gl-text-gray-500" - data-qa-selector="merged_status_content" - > - <strong v-if="mr.state !== 'closed'"> - {{ __('Merge details') }} - </strong> - <ul class="gl-pl-4 gl-m-0"> - <li v-if="mr.divergedCommitsCount > 0" class="gl-line-height-normal"> - <gl-sprintf - :message="s__('mrWidget|The source branch is %{link} the target branch')" - > - <template #link> - <gl-link :href="mr.targetBranchPath">{{ - n__('%d commit behind', '%d commits behind', mr.divergedCommitsCount) - }}</gl-link> - </template> - </gl-sprintf> - </li> - <li class="gl-line-height-normal"> - <added-commit-message - :state="mr.state" - :merge-commit-sha="mr.shortMergeCommitSha" - :is-squash-enabled="squashBeforeMerge" - :is-fast-forward-enabled="!shouldShowMergeEdit" - :commits-count="commitsCount" - :target-branch="stateData.targetBranch" - /> - </li> - <li v-if="mr.state !== 'closed'" class="gl-line-height-normal"> - {{ sourceBranchDeletedText }} - </li> - <li v-if="mr.relatedLinks" class="gl-line-height-normal"> - <related-links - :state="mr.state" - :related-links="mr.relatedLinks" - :show-assign-to-me="false" - class="mr-ready-merge-related-links gl-display-inline" - /> - </li> - </ul> - </div> - <div - v-else - :class="{ 'gl-mb-5': restructuredWidgetShowMergeButtons }" - class="gl-w-full gl-order-n1 gl-text-gray-500" - > - <added-commit-message - :is-squash-enabled="squashBeforeMerge" - :is-fast-forward-enabled="!shouldShowMergeEdit" - :commits-count="commitsCount" - :target-branch="stateData.targetBranch" - /> - <template v-if="mr.relatedLinks"> - · + </li> + <li v-if="mr.state !== 'closed'" class="gl-line-height-normal"> + {{ sourceBranchDeletedText }} + </li> + <li v-if="mr.relatedLinks" class="gl-line-height-normal"> <related-links :state="mr.state" :related-links="mr.relatedLinks" :show-assign-to-me="false" - :diverged-commits-count="mr.divergedCommitsCount" - :target-branch-path="mr.targetBranchPath" class="mr-ready-merge-related-links gl-display-inline" /> - </template> - </div> - </template> - </div> - <div - v-if="showDangerMessageForMergeTrain && !glFeatures.restructuredMrWidget" - class="gl-mt-5 gl-text-gray-500" - data-testid="failed-pipeline-merge-train-text" - > - {{ __('The latest pipeline for this merge request did not complete successfully.') }} + </li> + </ul> + </div> + <div + v-else + :class="{ 'gl-mb-5': shouldShowMergeControls }" + class="gl-w-full gl-order-n1 gl-text-gray-500" + > + <added-commit-message + :is-squash-enabled="squashBeforeMerge" + :is-fast-forward-enabled="!shouldShowMergeEdit" + :commits-count="commitsCount" + :target-branch="stateData.targetBranch" + /> + <template v-if="mr.relatedLinks"> + · + <related-links + :state="mr.state" + :related-links="mr.relatedLinks" + :show-assign-to-me="false" + :diverged-commits-count="mr.divergedCommitsCount" + :target-branch-path="mr.targetBranchPath" + class="mr-ready-merge-related-links gl-display-inline" + /> + </template> + </div> </div> </div> </div> - <template v-if="shouldShowMergeControls && !glFeatures.restructuredMrWidget"> - <div v-if="!shouldShowMergeEdit" class="mr-fast-forward-message"> - {{ __('Fast-forward merge without a merge commit') }} - </div> - <commits-header - v-if="!glFeatures.restructuredMrWidget && (shouldShowSquashEdit || shouldShowMergeEdit)" - :is-squash-enabled="squashBeforeMerge" - :commits-count="commitsCount" - :target-branch="stateData.targetBranch" - :is-fast-forward-enabled="!shouldShowMergeEdit" - :class="{ 'border-bottom': stateData.mergeError }" - > - <ul class="border-top content-list commits-list flex-list"> - <commit-edit - v-if="shouldShowSquashEdit" - :value="squashCommitMessage" - :label="__('Squash commit message')" - input-id="squash-message-edit" - squash - @input="setSquashCommitMessage" - > - <template #header> - <commit-message-dropdown :commits="commits" @input="setSquashCommitMessage" /> - </template> - </commit-edit> - <commit-edit - v-if="shouldShowMergeEdit" - :value="commitMessage" - :label="__('Merge commit message')" - input-id="merge-message-edit" - @input="setCommitMessage" - /> - <li> - <p class="form-text text-muted"> - <gl-sprintf :message="commitTemplateHintText"> - <template #link="{ content }"> - <gl-link :href="commitTemplateHelpPage" class="inline-link" target="_blank"> - {{ content }} - </gl-link> - </template> - </gl-sprintf> - </p> - </li> - </ul> - </commits-header> - </template> </template> </div> </template> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue index b1fbe150fcf..06f70bc456e 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue @@ -1,6 +1,5 @@ <script> import { GlButton } from '@gitlab/ui'; -import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { I18N_SHA_MISMATCH } from '../../i18n'; import statusIcon from '../mr_widget_status_icon.vue'; @@ -13,7 +12,6 @@ export default { i18n: { I18N_SHA_MISMATCH, }, - mixins: [glFeatureFlagMixin()], props: { mr: { type: Object, @@ -28,8 +26,7 @@ export default { <status-icon :show-disabled-button="false" status="warning" /> <div class="media-body"> <span - :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" - class="gl-font-weight-bold" + class="gl-ml-0! gl-text-body! gl-font-weight-bold" data-qa-selector="head_mismatch_content" > {{ $options.i18n.I18N_SHA_MISMATCH.warningMessage }} diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue index c6227c4394d..1413a46b4b9 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue @@ -1,6 +1,5 @@ <script> import { GlIcon, GlTooltipDirective, GlFormCheckbox, GlLink } from '@gitlab/ui'; -import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { SQUASH_BEFORE_MERGE } from '../../i18n'; export default { @@ -12,7 +11,6 @@ export default { directives: { GlTooltip: GlTooltipDirective, }, - mixins: [glFeatureFlagsMixin()], i18n: { ...SQUASH_BEFORE_MERGE, }, @@ -36,9 +34,6 @@ export default { tooltipTitle() { return this.isDisabled ? this.$options.i18n.tooltipTitle : null; }, - helpIconName() { - return this.glFeatures.restructuredMrWidget ? 'question-o' : 'question'; - }, }, }; </script> @@ -62,10 +57,10 @@ export default { v-gl-tooltip :href="helpPath" :title="$options.i18n.helpLabel" - :class="{ 'gl-text-blue-600': glFeatures.restructuredMrWidget }" + class="gl-text-blue-600" target="_blank" > - <gl-icon :name="helpIconName" /> + <gl-icon name="question-o" /> <span class="sr-only"> {{ $options.i18n.helpLabel }} </span> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue index 25ba4bf12af..7e9ebcf0b2e 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue @@ -1,6 +1,5 @@ <script> import { GlButton } from '@gitlab/ui'; -import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import notesEventHub from '~/notes/event_hub'; import statusIcon from '../mr_widget_status_icon.vue'; @@ -10,7 +9,6 @@ export default { statusIcon, GlButton, }, - mixins: [glFeatureFlagMixin()], props: { mr: { type: Object, @@ -29,22 +27,15 @@ export default { <div class="mr-widget-body media gl-flex-wrap"> <status-icon show-disabled-button status="warning" /> <div class="media-body"> - <span - :class="{ - 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget, - 'gl-display-block': !glFeatures.restructuredMrWidget, - }" - class="gl-ml-3 gl-font-weight-bold gl-w-100" - > + <span class="gl-ml-0! gl-text-body! gl-ml-3 gl-font-weight-bold gl-w-100"> {{ s__('mrWidget|Merge blocked: all threads must be resolved.') }} </span> <gl-button data-testid="jump-to-first" class="gl-ml-3" size="small" - :icon="glFeatures.restructuredMrWidget ? undefined : 'comment-next'" - :variant="glFeatures.restructuredMrWidget ? 'confirm' : 'default'" - :category="glFeatures.restructuredMrWidget ? 'secondary' : 'primary'" + variant="confirm" + category="secondary" @click="jumpToFirstUnresolvedDiscussion" > {{ s__('mrWidget|Jump to first unresolved thread') }} @@ -54,7 +45,6 @@ export default { :href="mr.createIssueToResolveDiscussionsPath" class="js-create-issue gl-ml-3" size="small" - :icon="glFeatures.restructuredMrWidget ? undefined : 'issue-new'" > {{ s__('mrWidget|Create issue to resolve all threads') }} </gl-button> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue index 5bd7745d704..501aee1a18d 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue @@ -167,10 +167,7 @@ export default { <status-icon :show-disabled-button="canUpdate" status="warning" /> <div class="media-body"> <div class="float-left"> - <span - :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" - class="gl-font-weight-bold" - > + <span class="gl-ml-0! gl-text-body! gl-font-weight-bold"> {{ __("Merge blocked: merge request must be marked as ready. It's still marked as draft.") }} diff --git a/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js b/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js index 627ddb0445e..d964b4bacac 100644 --- a/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js +++ b/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js @@ -20,13 +20,6 @@ export default { this.mr.preventMerge, ); }, - shouldShowMergeControls() { - if (this.glFeatures.restructuredMrWidget) { - return this.restructuredWidgetShowMergeButtons; - } - - return this.isMergeAllowed || this.isAutoMergeAvailable; - }, mergeDisabledText() { if (this.pipeline?.status === PIPELINE_SKIPPED_STATUS) { return MERGE_DISABLED_SKIPPED_PIPELINE_TEXT; diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue index 3e0ac236fdf..0edd44d835e 100644 --- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue +++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue @@ -17,7 +17,6 @@ import { setFaviconOverlay } from '../lib/utils/favicon'; import Loading from './components/loading.vue'; import MrWidgetAlertMessage from './components/mr_widget_alert_message.vue'; import MrWidgetPipelineContainer from './components/mr_widget_pipeline_container.vue'; -import WidgetRelatedLinks from './components/mr_widget_related_links.vue'; import WidgetSuggestPipeline from './components/mr_widget_suggest_pipeline.vue'; import SourceBranchRemovalStatus from './components/source_branch_removal_status.vue'; import ArchivedState from './components/states/mr_widget_archived.vue'; @@ -61,7 +60,6 @@ export default { ExtensionsContainer, 'mr-widget-suggest-pipeline': WidgetSuggestPipeline, MrWidgetPipelineContainer, - 'mr-widget-related-links': WidgetRelatedLinks, MrWidgetAlertMessage, 'mr-widget-merged': MergedState, 'mr-widget-closed': ClosedState, @@ -73,9 +71,7 @@ export default { 'mr-widget-nothing-to-merge': NothingToMergeState, 'mr-widget-not-allowed': NotAllowedState, 'mr-widget-missing-branch': MissingBranchState, - 'mr-widget-ready-to-merge': window.gon?.features?.restructuredMrWidget - ? () => import('./components/states/new_ready_to_merge.vue') - : ReadyToMergeState, + 'mr-widget-ready-to-merge': () => import('./components/states/new_ready_to_merge.vue'), 'sha-mismatch': ShaMismatch, 'mr-widget-checking': CheckingState, 'mr-widget-unresolved-discussions': UnresolvedDiscussionsState, @@ -163,12 +159,6 @@ export default { shouldRenderCodeQuality() { return this.mr?.codequalityReportsPath; }, - shouldRenderRelatedLinks() { - return ( - (Boolean(this.mr.relatedLinks) || this.mr.divergedCommitsCount > 0) && - !this.mr.isNothingToMergeState - ); - }, shouldRenderSourceBranchRemovalStatus() { return ( !this.mr.canRemoveSourceBranch && @@ -239,9 +229,6 @@ export default { shouldShowCodeQualityExtension() { return window.gon?.features?.refactorCodeQualityExtension; }, - isRestructuredMrWidgetEnabled() { - return window.gon?.features?.restructuredMrWidget; - }, }, watch: { 'mr.machineValue': { @@ -638,23 +625,7 @@ export default { <div class="mr-widget-section" data-qa-selector="mr_widget_content"> <component :is="componentName" :mr="mr" :service="service" /> - <ready-to-merge - v-if="isRestructuredMrWidgetEnabled && mr.commitsCount" - :mr="mr" - :service="service" - /> - <div v-else class="mr-widget-info"> - <mr-widget-related-links - v-if="shouldRenderRelatedLinks" - :state="mr.state" - :related-links="mr.relatedLinks" - :diverged-commits-count="mr.divergedCommitsCount" - :target-branch-path="mr.targetBranchPath" - class="mr-info-list gl-ml-7 gl-pb-5" - /> - - <source-branch-removal-status v-if="shouldRenderSourceBranchRemovalStatus" /> - </div> + <ready-to-merge v-if="mr.commitsCount" :mr="mr" :service="service" /> </div> </div> <mr-widget-pipeline-container diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js b/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js index 18d955652ba..7a458f9ce7e 100644 --- a/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js +++ b/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js @@ -27,8 +27,6 @@ export default function deviseState() { return stateKey.shaMismatch; } else if (this.autoMergeEnabled && !this.mergeError) { return stateKey.autoMergeEnabled; - } else if (!this.canMerge && !window.gon?.features?.restructuredMrWidget) { - return stateKey.notAllowedToMerge; } else if (this.canBeMerged) { return stateKey.readyToMerge; } diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 6f1f37b86cf..13ebe57a4d9 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -34,7 +34,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo before_action only: [:show] do push_frontend_feature_flag(:merge_request_widget_graphql, project) push_frontend_feature_flag(:core_security_mr_widget_counts, project) - push_frontend_feature_flag(:restructured_mr_widget, project) push_frontend_feature_flag(:refactor_mr_widgets_extensions, project) push_frontend_feature_flag(:refactor_code_quality_extension, project) push_frontend_feature_flag(:refactor_mr_widget_test_summary, project) diff --git a/app/serializers/issue_entity.rb b/app/serializers/issue_entity.rb index ea43ed87d22..7ff75927fcd 100644 --- a/app/serializers/issue_entity.rb +++ b/app/serializers/issue_entity.rb @@ -47,6 +47,10 @@ class IssueEntity < IssuableEntity can?(request.current_user, :update_issue, issue) end + expose :can_set_issue_metadata do |issue| + can?(request.current_user, :set_issue_metadata, issue) + end + expose :can_award_emoji do |issue| can?(request.current_user, :award_emoji, issue) end diff --git a/app/views/projects/pages/_use.html.haml b/app/views/projects/pages/_use.html.haml index 20e6338fa76..f865fac0e88 100644 --- a/app/views/projects/pages/_use.html.haml +++ b/app/views/projects/pages/_use.html.haml @@ -4,7 +4,8 @@ = s_('GitLabPages|Configure pages') .card-body %p.gl-mb-0 - - docs_link_start = "<a href='#{help_page_path('user/project/pages/index')}' target='_blank' rel='noopener noreferrer'>".html_safe - - samples_link_start = "<a href='https://gitlab.com/pages' target='_blank' rel='noopener noreferrer'>".html_safe + - docs_link_start = "<a href='#{help_page_path('user/project/pages/index')}' target='_blank' rel='noopener noreferrer' data-track-action='click_link' data-track-label='pages_docs_link'>".html_safe + - samples_link_start = "<a href='https://gitlab.com/pages' target='_blank' rel='noopener noreferrer' data-track-action='click_link' data-track-label='pages_samples_link>" + .html_safe - link_end = '</a>'.html_safe = s_('GitLabPages|Your Pages site is not configured yet. See the %{docs_link_start}GitLab Pages documentation%{link_end} to learn how to upload your static site and have GitLab serve it. You can also take some inspiration from the %{samples_link_start}sample Pages projects%{link_end}.').html_safe % { docs_link_start: docs_link_start, samples_link_start: samples_link_start, link_end: link_end } diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml index e90ea35f28e..58db071a8d1 100644 --- a/app/views/shared/issuable/_form.html.haml +++ b/app/views/shared/issuable/_form.html.haml @@ -3,7 +3,7 @@ - project = @target_project || @project - presenter = local_assigns.fetch(:presenter, nil) -= form_errors(issuable) += form_errors(issuable, pajamas_alert: true) - if @conflict = render Pajamas::AlertComponent.new(variant: :danger, diff --git a/app/workers/concerns/waitable_worker.rb b/app/workers/concerns/waitable_worker.rb index 336d60d46ac..9300c2a5790 100644 --- a/app/workers/concerns/waitable_worker.rb +++ b/app/workers/concerns/waitable_worker.rb @@ -7,7 +7,7 @@ module WaitableWorker # Schedules multiple jobs and waits for them to be completed. def bulk_perform_and_wait(args_list) # Short-circuit: it's more efficient to do small numbers of jobs inline - if args_list.size == 1 + if args_list.size == 1 && !always_async_project_authorizations_refresh? return bulk_perform_inline(args_list) end @@ -29,6 +29,10 @@ module WaitableWorker bulk_perform_async(failed) if failed.present? end + + def always_async_project_authorizations_refresh? + Feature.enabled?(:always_async_project_authorizations_refresh) + end end def perform(*args) diff --git a/config/feature_flags/development/restructured_mr_widget.yml b/config/feature_flags/development/always_async_project_authorizations_refresh.yml index cf20130509a..233be4d930e 100644 --- a/config/feature_flags/development/restructured_mr_widget.yml +++ b/config/feature_flags/development/always_async_project_authorizations_refresh.yml @@ -1,8 +1,8 @@ --- -name: restructured_mr_widget -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68565 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339181 -milestone: '14.3' +name: always_async_project_authorizations_refresh +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92333 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/367683 +milestone: '15.3' type: development -group: group::code review -default_enabled: true +group: group::workspace +default_enabled: false diff --git a/doc/administration/package_information/supported_os.md b/doc/administration/package_information/supported_os.md index 4f31981a05c..739ba80ea2b 100644 --- a/doc/administration/package_information/supported_os.md +++ b/doc/administration/package_information/supported_os.md @@ -23,7 +23,7 @@ The following lists the currently supported OSs and their possible EOL dates. | Debian 10 | GitLab CE / GitLab EE 12.2.0 | amd64, arm64 | [Debian Install Documentation](https://about.gitlab.com/install/#debian) | 2024 | <https://wiki.debian.org/LTS> | | Debian 11 | GitLab CE / GitLab EE 14.6.0 | amd64, arm64 | [Debian Install Documentation](https://about.gitlab.com/install/#debian) | 2026 | <https://wiki.debian.org/LTS> | | OpenSUSE 15.3 | GitLab CE / GitLab EE 14.5.0 | x86_64, aarch64 | [OpenSUSE Install Documentation](https://about.gitlab.com/install/#opensuse-leap-15-3) | Nov 2022 | <https://en.opensuse.org/Lifetime> | -| RHEL 8 | GitLab CE / GitLab EE 12.8.1 | x86_64, arm64 | [Use CentOS Install Documentation](https://about.gitlab.com/install/#centos-7) | May 2024 | [RHEL Details](https://access.redhat.com/support/policy/updates/errata/#Life_Cycle_Dates) | +| RHEL 8 | GitLab CE / GitLab EE 12.8.1 | x86_64, arm64 | [Use CentOS Install Documentation](https://about.gitlab.com/install/#centos-7) | May 2029 | [RHEL Details](https://access.redhat.com/support/policy/updates/errata/#Life_Cycle_Dates) | | SLES 12 | GitLab EE 9.0.0 | x86_64 | [Use OpenSUSE Install Documentation](https://about.gitlab.com/install/#opensuse-leap-15-3) | Oct 2027 | <https://www.suse.com/lifecycle/> | | Oracle Linux | GitLab CE / GitLab EE 8.14.0 | x86_64 | [Use CentOS Install Documentation](https://about.gitlab.com/install/#centos-7) | Jul 2024 | <https://www.oracle.com/a/ocom/docs/elsp-lifetime-069338.pdf> | | Scientific Linux | GitLab CE / GitLab EE 8.14.0 | x86_64 | [Use CentOS Install Documentation](https://about.gitlab.com/install/#centos-7) | June 2024 | <https://scientificlinux.org/downloads/sl-versions/sl7/> | diff --git a/doc/ci/pipeline_editor/index.md b/doc/ci/pipeline_editor/index.md index 4fb2ec94d60..d9687e4f9fc 100644 --- a/doc/ci/pipeline_editor/index.md +++ b/doc/ci/pipeline_editor/index.md @@ -40,6 +40,10 @@ is invalid, a tip is shown to help you fix the problem: ## Lint CI configuration +NOTE: +The **Lint** tab is replaced with the **Validate** tab when [pipeline simulations](#simulate-a-cicd-pipeline) +are enabled. + To test the validity of your GitLab CI/CD configuration before committing the changes, you can use the CI lint tool. To access it, go to **CI/CD > Editor** and select the **Lint** tab. @@ -51,6 +55,20 @@ reflected in the CI lint. It displays the same results as the existing [CI Lint ![Linting errors in a CI configuration](img/pipeline_editor_lint_v13_8.png) +## Simulate a CI/CD pipeline + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/337282) in GitLab 15.3 [with a flag](../../administration/feature_flags.md) named `simulate_pipeline`. Disabled by default. + +FLAG: +On self-managed GitLab, by default this feature is not available. To make it available, +ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `simulate_pipeline`. +The feature is not ready for production use. When this feature is enabled, it replaces the **Lint** tab. + +To look for pipeline syntax and logic issues, you can simulate the creation of a +GitLab CI/CD pipeline in the **Validate** tab. A pipeline simulation can help find +problems such as incorrect `rules` and `needs` job dependencies, and is similar to +simulations in the [CI Lint tool](../lint.md#simulate-a-pipeline). + ## View included CI/CD configuration > - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/7064) in GitLab 15.0 [with a flag](../../administration/feature_flags.md) named `pipeline_editor_file_tree`. Disabled by default. diff --git a/doc/development/documentation/restful_api_styleguide.md b/doc/development/documentation/restful_api_styleguide.md index 30bd5e27411..bf1461a810d 100644 --- a/doc/development/documentation/restful_api_styleguide.md +++ b/doc/development/documentation/restful_api_styleguide.md @@ -104,6 +104,9 @@ for the section. For example: > `widget_message` [introduced](<link-to-issue>) in GitLab 14.3. ``` +If the API or attribute is deployed behind a feature flag, +[include the feature flag information](feature_flags.md) in the version history. + ## Deprecations To document the deprecation of an API endpoint, follow the steps to diff --git a/doc/development/documentation/site_architecture/index.md b/doc/development/documentation/site_architecture/index.md index 2fe4494bc37..1dadbaa7051 100644 --- a/doc/development/documentation/site_architecture/index.md +++ b/doc/development/documentation/site_architecture/index.md @@ -66,10 +66,10 @@ you should keep the documentation with the code in that repository. Then you can use one of these approaches: -- (Recommended) [Add the repository to the list of products](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/doc/development.md#add-a-new-product) +- Recommended. [Add the repository to the list of products](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/doc/development.md#add-a-new-product) published at <https://docs.gitlab.com>. The source of the documentation pages remains in the external repository, but the resulting pages are indexed and searchable on <https://docs.gitlab.com>. -- (Recommended) [Add an entry in the global navigation](global_nav.md#add-a-navigation-entry) for +- Recommended. [Add an entry in the global navigation](global_nav.md#add-a-navigation-entry) for <https://docs.gitlab.com> that links directly to the documentation in that external repository. The documentation pages are not indexed or searchable on <https://docs.gitlab.com>. View [an example](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/fedb6378a3c92274ba3b6031df0d34455594e4cc/content/_data/navigation.yaml#L2944-L2946). diff --git a/lib/gitlab/memory/reports_daemon.rb b/lib/gitlab/memory/reports_daemon.rb index 2b2e0915e72..779c19b3a1e 100644 --- a/lib/gitlab/memory/reports_daemon.rb +++ b/lib/gitlab/memory/reports_daemon.rb @@ -41,7 +41,7 @@ module Gitlab end log_report(report_label(report), tms) - @report_duration_counter.increment({ report: report_label(report) }, tms.real.to_i) + @report_duration_counter.increment({ report: report_label(report) }, tms.real) sleep sleep_between_reports_s end @@ -63,7 +63,7 @@ module Gitlab message: 'finished', pid: $$, worker_id: worker_id, - report: report_label, + perf_report: report_label, duration_s: tms.real.round(2), cpu_s: tms.utime.round(2), sys_cpu_s: tms.stime.round(2) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 1cf6a679287..8e5cd06dc39 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -12466,9 +12466,6 @@ msgstr "" msgid "Deletes the source branch" msgstr "" -msgid "Deletes the source branch." -msgstr "" - msgid "Deleting" msgstr "" @@ -13732,9 +13729,6 @@ msgstr "" msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)" msgstr "" -msgid "Does not delete the source branch." -msgstr "" - msgid "Domain" msgstr "" @@ -16021,9 +16015,6 @@ msgstr "" msgid "Fast timeout" msgstr "" -msgid "Fast-forward merge without a merge commit" -msgstr "" - msgid "Faster releases. Better code. Less pain." msgstr "" @@ -38957,9 +38948,6 @@ msgstr "" msgid "The latest artifacts created by jobs in the most recent successful pipeline will be stored." msgstr "" -msgid "The latest pipeline for this merge request did not complete successfully." -msgstr "" - msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified." msgstr "" @@ -39488,9 +39476,6 @@ msgstr "" msgid "There was an error removing the e-mail." msgstr "" -msgid "There was an error resetting group pipeline minutes." -msgstr "" - msgid "There was an error resetting user pipeline minutes." msgstr "" @@ -46292,12 +46277,6 @@ msgstr "" msgid "mrWidgetCommitsAdded|1 merge commit" msgstr "" -msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}." -msgstr "" - -msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}." -msgstr "" - msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}." msgstr "" @@ -46414,9 +46393,6 @@ msgstr "" msgid "mrWidget|Delete source branch" msgstr "" -msgid "mrWidget|Deletes the source branch" -msgstr "" - msgid "mrWidget|Deployment statistics are not available currently" msgstr "" @@ -46426,9 +46402,6 @@ msgstr "" msgid "mrWidget|Dismiss" msgstr "" -msgid "mrWidget|Does not delete the source branch" -msgstr "" - msgid "mrWidget|Failed to load deployment statistics" msgstr "" @@ -46464,9 +46437,6 @@ msgid_plural "mrWidget|Mentions issues" msgstr[0] "" msgstr[1] "" -msgid "mrWidget|Merge" -msgstr "" - msgid "mrWidget|Merge blocked: all required approvals must be given." msgstr "" @@ -46500,9 +46470,6 @@ msgstr "" msgid "mrWidget|Merged by" msgstr "" -msgid "mrWidget|Merges changes into" -msgstr "" - msgid "mrWidget|Merging! Changes are being shipped…" msgstr "" @@ -46587,21 +46554,9 @@ msgstr "" msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist." msgstr "" -msgid "mrWidget|The changes were merged into" -msgstr "" - -msgid "mrWidget|The changes were not merged into" -msgstr "" - -msgid "mrWidget|The source branch has been deleted" -msgstr "" - msgid "mrWidget|The source branch is %{link} the target branch" msgstr "" -msgid "mrWidget|The source branch is being deleted" -msgstr "" - msgid "mrWidget|This merge request failed to be merged automatically" msgstr "" diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb index 27c12a4e21f..8e2959abb2f 100644 --- a/qa/qa/page/merge_request/show.rb +++ b/qa/qa/page/merge_request/show.rb @@ -71,7 +71,6 @@ module QA view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue' do element :cherry_pick_button - element :merged_status_content element :revert_button end diff --git a/spec/features/merge_request/user_merges_merge_request_spec.rb b/spec/features/merge_request/user_merges_merge_request_spec.rb index 6a9a30953df..c91dc7b1c00 100644 --- a/spec/features/merge_request/user_merges_merge_request_spec.rb +++ b/spec/features/merge_request/user_merges_merge_request_spec.rb @@ -21,27 +21,6 @@ RSpec.describe "User merges a merge request", :js do end end - context "ff-only merge" do - let(:project) { create(:project, :public, :repository, merge_requests_ff_only_enabled: true) } - - before do - stub_feature_flags(restructured_mr_widget: false) - visit(merge_request_path(merge_request)) - end - - context "when branch is rebased" do - let!(:merge_request) { create(:merge_request, :rebased, source_project: project) } - - it_behaves_like "fast forward merge a merge request" - end - - context "when branch is merged" do - let!(:merge_request) { create(:merge_request, :merged_target, source_project: project) } - - it_behaves_like "fast forward merge a merge request" - end - end - context 'sidebar merge requests counter' do let(:project) { create(:project, :public, :repository) } let!(:merge_request) { create(:merge_request, source_project: project) } diff --git a/spec/frontend/notes/components/note_actions_spec.js b/spec/frontend/notes/components/note_actions_spec.js index bf5a6b4966a..524b6c442cf 100644 --- a/spec/frontend/notes/components/note_actions_spec.js +++ b/spec/frontend/notes/components/note_actions_spec.js @@ -159,7 +159,7 @@ describe('noteActions', () => { }); }); - describe('when a user has access to edit an issue', () => { + describe('when a user can set metadata of an issue', () => { const testButtonClickTriggersAction = () => { axiosMock.onPut(`${TEST_HOST}/api/v4/projects/group/project/issues/1`).reply(() => { expect(actions.updateAssignees).toHaveBeenCalled(); @@ -176,7 +176,7 @@ describe('noteActions', () => { }); store.state.noteableData = { current_user: { - can_update: true, + can_set_issue_metadata: true, }, }; store.state.userData = userDataMock; @@ -191,6 +191,31 @@ describe('noteActions', () => { it('should be possible to unassign the comment author', testButtonClickTriggersAction); }); + describe('when a user can update but not set metadata of an issue', () => { + beforeEach(() => { + wrapper = mountNoteActions(props, { + targetType: () => 'issue', + }); + store.state.noteableData = { + current_user: { + can_update: true, + can_set_issue_metadata: false, + }, + }; + store.state.userData = userDataMock; + }); + + afterEach(() => { + wrapper.destroy(); + axiosMock.restore(); + }); + + it('should not be possible to assign or unassign the comment author', () => { + const assignUserButton = wrapper.find('[data-testid="assign-user"]'); + expect(assignUserButton.exists()).toBe(false); + }); + }); + describe('when a user does not have access to edit an issue', () => { const testButtonDoesNotRender = () => { const assignUserButton = wrapper.find('[data-testid="assign-user"]'); diff --git a/spec/frontend/vue_mr_widget/components/added_commit_message_spec.js b/spec/frontend/vue_mr_widget/components/added_commit_message_spec.js index 150680caa7e..cb53dc1fb61 100644 --- a/spec/frontend/vue_mr_widget/components/added_commit_message_spec.js +++ b/spec/frontend/vue_mr_widget/components/added_commit_message_spec.js @@ -10,11 +10,6 @@ function factory(propsData) { targetBranch: 'main', ...propsData, }, - provide: { - glFeatures: { - restructuredMrWidget: true.valueOf, - }, - }, }); } diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_status_icon_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_status_icon_spec.js index c25e10c5249..11373be578a 100644 --- a/spec/frontend/vue_mr_widget/components/mr_widget_status_icon_spec.js +++ b/spec/frontend/vue_mr_widget/components/mr_widget_status_icon_spec.js @@ -6,7 +6,6 @@ describe('MR widget status icon component', () => { let wrapper; const findLoadingIcon = () => wrapper.find(GlLoadingIcon); - const findDisabledMergeButton = () => wrapper.find('[data-testid="disabled-merge-button"]'); const createWrapper = (props, mountFn = shallowMount) => { wrapper = mountFn(mrStatusIcon, { @@ -41,20 +40,4 @@ describe('MR widget status icon component', () => { expect(wrapper.find('[data-testid="status_failed-icon"]').exists()).toBe(true); }); }); - - describe('with disabled button', () => { - it('renders a disabled button', () => { - createWrapper({ status: 'failed', showDisabledButton: true }); - - expect(findDisabledMergeButton().exists()).toBe(true); - }); - }); - - describe('without disabled button', () => { - it('does not render a disabled button', () => { - createWrapper({ status: 'failed' }); - - expect(findDisabledMergeButton().exists()).toBe(false); - }); - }); }); diff --git a/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap b/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap index 56a0218b374..e591698aa90 100644 --- a/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap +++ b/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap @@ -40,34 +40,6 @@ exports[`MRWidgetAutoMergeEnabled when graphql is disabled template should have </gl-button-stub> </h4> - - <section - class="mr-info-list" - > - <p - class="gl-display-flex" - > - <span - class="gl-mr-3" - > - Does not delete the source branch - </span> - - <gl-button-stub - buttontextclasses="" - category="primary" - class="js-remove-source-branch" - data-testid="removeSourceBranchButton" - icon="" - size="small" - variant="default" - > - - Delete source branch - - </gl-button-stub> - </p> - </section> </div> </div> `; @@ -112,34 +84,6 @@ exports[`MRWidgetAutoMergeEnabled when graphql is enabled template should have c </gl-button-stub> </h4> - - <section - class="mr-info-list" - > - <p - class="gl-display-flex" - > - <span - class="gl-mr-3" - > - Does not delete the source branch - </span> - - <gl-button-stub - buttontextclasses="" - category="primary" - class="js-remove-source-branch" - data-testid="removeSourceBranchButton" - icon="" - size="small" - variant="default" - > - - Delete source branch - - </gl-button-stub> - </p> - </section> </div> </div> `; diff --git a/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_pipeline_failed_spec.js.snap b/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_pipeline_failed_spec.js.snap index 98297630792..7e741bf4660 100644 --- a/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_pipeline_failed_spec.js.snap +++ b/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_pipeline_failed_spec.js.snap @@ -5,7 +5,7 @@ exports[`PipelineFailed should render error message with a disabled merge button class="mr-widget-body media" > <status-icon-stub - showdisabledbutton="true" + show-disabled-button="true" status="warning" /> @@ -13,7 +13,7 @@ exports[`PipelineFailed should render error message with a disabled merge button class="media-body space-children" > <span - class="bold" + class="gl-ml-0! gl-text-body! bold" > <gl-sprintf-stub message="Merge blocked: pipeline must succeed. Push a commit that fixes the failure, or %{linkStart}learn about other solutions.%{linkEnd}" diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_archived_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_archived_spec.js index f3061d792d0..9332b7e334a 100644 --- a/spec/frontend/vue_mr_widget/components/states/mr_widget_archived_spec.js +++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_archived_spec.js @@ -18,11 +18,6 @@ describe('MRWidgetArchived', () => { expect(vm.$el.querySelector('.ci-status-icon')).not.toBeNull(); }); - it('renders a disabled button', () => { - expect(vm.$el.querySelector('button').getAttribute('disabled')).toEqual('disabled'); - expect(vm.$el.querySelector('button').textContent.trim()).toEqual('Merge'); - }); - it('renders information', () => { expect(vm.$el.querySelector('.bold').textContent.trim()).toEqual( 'Merge unavailable: merge requests are read-only on archived projects.', diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js index 7387ed2d5e9..5bbc5d4a106 100644 --- a/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js +++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js @@ -102,74 +102,6 @@ describe('MRWidgetAutoMergeEnabled', () => { }); describe('computed', () => { - describe('canRemoveSourceBranch', () => { - it('should return true when user is able to remove source branch', () => { - factory({ - ...defaultMrProps(), - }); - - expect(wrapper.findByTestId('removeSourceBranchButton').exists()).toBe(true); - }); - - it.each` - mergeUserId | currentUserId - ${2} | ${1} - ${1} | ${2} - `( - 'should return false when user id is not the same with who set the MWPS', - ({ mergeUserId, currentUserId }) => { - factory({ - ...defaultMrProps(), - mergeUserId, - currentUserId, - }); - - expect(wrapper.findByTestId('removeSourceBranchButton').exists()).toBe(false); - }, - ); - - it('should not find "Delete" button when shouldRemoveSourceBranch set to true', () => { - factory({ - ...defaultMrProps(), - shouldRemoveSourceBranch: true, - }); - - expect(wrapper.findByTestId('removeSourceBranchButton').exists()).toBe(false); - }); - - it('should find "Delete" button when shouldRemoveSourceBranch overrides state.forceRemoveSourceBranch', () => { - factory( - { - ...defaultMrProps(), - shouldRemoveSourceBranch: false, - }, - { - forceRemoveSourceBranch: true, - }, - ); - - expect(wrapper.findByTestId('removeSourceBranchButton').exists()).toBe(true); - }); - - it('should find "Delete" button when shouldRemoveSourceBranch set to false', () => { - factory({ - ...defaultMrProps(), - shouldRemoveSourceBranch: false, - }); - - expect(wrapper.findByTestId('removeSourceBranchButton').exists()).toBe(true); - }); - - it('should return false if user is not able to remove the source branch', () => { - factory({ - ...defaultMrProps(), - canRemoveSourceBranch: false, - }); - - expect(wrapper.findByTestId('removeSourceBranchButton').exists()).toBe(false); - }); - }); - describe('cancelButtonText', () => { it('should return "Cancel" if MWPS is selected', () => { factory({ @@ -265,42 +197,6 @@ describe('MRWidgetAutoMergeEnabled', () => { expect(wrapper.find('.js-cancel-auto-merge').props('loading')).toBe(true); }); - it('should show source branch will be deleted text when it source branch set to remove', () => { - factory({ - ...defaultMrProps(), - shouldRemoveSourceBranch: true, - }); - - const normalizedText = wrapper.text().replace(/\s+/g, ' '); - - expect(normalizedText).toContain('Deletes the source branch'); - expect(normalizedText).not.toContain('Does not delete the source branch'); - }); - - it('should not show delete source branch button when user not able to delete source branch', () => { - factory({ - ...defaultMrProps(), - currentUserId: 4, - }); - - expect(wrapper.find('.js-remove-source-branch').exists()).toBe(false); - }); - - it('should disable delete source branch button when the action is in progress', async () => { - factory({ - ...defaultMrProps(), - }); - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ - isRemovingSourceBranch: true, - }); - - await nextTick(); - - expect(wrapper.find('.js-remove-source-branch').props('loading')).toBe(true); - }); - it('should render the status text as "...to merged automatically" if MWPS is selected', () => { factory({ ...defaultMrProps(), diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_checking_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_checking_spec.js index afe6bd0e767..02de426204b 100644 --- a/spec/frontend/vue_mr_widget/components/states/mr_widget_checking_spec.js +++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_checking_spec.js @@ -15,10 +15,6 @@ describe('MRWidgetChecking', () => { vm.$destroy(); }); - it('renders disabled button', () => { - expect(vm.$el.querySelector('button').getAttribute('disabled')).toEqual('disabled'); - }); - it('renders loading icon', () => { expect(vm.$el.querySelector('.mr-widget-icon span').classList).toContain('gl-spinner'); }); diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_closed_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_closed_spec.js index 6ae218ce6f8..f7d046eb8f9 100644 --- a/spec/frontend/vue_mr_widget/components/states/mr_widget_closed_spec.js +++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_closed_spec.js @@ -36,28 +36,4 @@ describe('MRWidgetClosed', () => { it('renders warning icon', () => { expect(vm.$el.querySelector('.js-ci-status-icon-warning')).not.toBeNull(); }); - - it('renders closed by information with author and time', () => { - expect( - vm.$el.querySelector('.js-mr-widget-author').textContent.trim().replace(/\s\s+/g, ' '), - ).toContain('Closed by Administrator less than a minute ago'); - }); - - it('links to the user that closed the MR', () => { - expect(vm.$el.querySelector('.author-link').getAttribute('href')).toEqual( - 'http://localhost:3000/root', - ); - }); - - it('renders information about the changes not being merged', () => { - expect( - vm.$el.querySelector('.mr-info-list').textContent.trim().replace(/\s\s+/g, ' '), - ).toContain('The changes were not merged into so_long_jquery'); - }); - - it('renders link for target branch', () => { - expect(vm.$el.querySelector('.label-branch').getAttribute('href')).toEqual( - '/twitter/flight/commits/so_long_jquery', - ); - }); }); diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js index 6d8e7056366..a9c1d602a37 100644 --- a/spec/frontend/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js +++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js @@ -1,6 +1,5 @@ import { shallowMount } from '@vue/test-utils'; import { nextTick } from 'vue'; -import StatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue'; import MrWidgetFailedToMerge from '~/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue'; import eventHub from '~/vue_merge_request_widget/event_hub'; @@ -116,7 +115,6 @@ describe('MRWidgetFailedToMerge', () => { it('renders warning icon and disabled merge button', () => { expect(wrapper.find('.js-ci-status-icon-warning')).not.toBeNull(); - expect(wrapper.find(StatusIcon).props('showDisabledButton')).toBe(true); }); it('renders given error', () => { diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js index 29ee7e0010f..2606933450e 100644 --- a/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js +++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js @@ -1,5 +1,5 @@ import { getByRole } from '@testing-library/dom'; -import Vue, { nextTick } from 'vue'; +import Vue from 'vue'; import mountComponent from 'helpers/vue_mount_component_helper'; import waitForPromises from 'helpers/wait_for_promises'; import { OPEN_REVERT_MODAL, OPEN_CHERRY_PICK_MODAL } from '~/projects/commit/constants'; @@ -10,14 +10,6 @@ import eventHub from '~/vue_merge_request_widget/event_hub'; describe('MRWidgetMerged', () => { let vm; const targetBranch = 'foo'; - const selectors = { - get copyMergeShaButton() { - return vm.$el.querySelector('button.js-mr-merged-copy-sha'); - }, - get mergeCommitShaLink() { - return vm.$el.querySelector('a.js-mr-merged-commit-sha'); - }, - }; beforeEach(() => { jest.spyOn(document, 'dispatchEvent'); @@ -177,58 +169,11 @@ describe('MRWidgetMerged', () => { expect(vm.$el.textContent).toContain('Administrator'); }); - it('renders branch information', () => { - expect(vm.$el.textContent).toContain('The changes were merged into'); - expect(vm.$el.textContent).toContain(targetBranch); - }); - - it('renders information about branch being deleted', () => { - expect(vm.$el.textContent).toContain('The source branch has been deleted'); - }); - it('shows revert and cherry-pick buttons', () => { expect(vm.$el.textContent).toContain('Revert'); expect(vm.$el.textContent).toContain('Cherry-pick'); }); - it('shows button to copy commit SHA to clipboard', () => { - expect(selectors.copyMergeShaButton).not.toBe(null); - expect(selectors.copyMergeShaButton.dataset.clipboardText).toBe(vm.mr.mergeCommitSha); - }); - - it('hides button to copy commit SHA if SHA does not exist', async () => { - vm.mr.mergeCommitSha = null; - - await nextTick(); - - expect(selectors.copyMergeShaButton).toBe(null); - expect(vm.$el.querySelector('.mr-info-list').innerText).not.toContain('with'); - }); - - it('shows merge commit SHA link', () => { - expect(selectors.mergeCommitShaLink).not.toBe(null); - expect(selectors.mergeCommitShaLink.text).toContain(vm.mr.shortMergeCommitSha); - expect(selectors.mergeCommitShaLink.href).toBe(vm.mr.mergeCommitPath); - }); - - it('should not show source branch deleted text', async () => { - vm.mr.sourceBranchRemoved = false; - - await nextTick(); - - expect(vm.$el.innerText).not.toContain('The source branch has been deleted'); - }); - - it('should show source branch deleting text', async () => { - vm.mr.isRemovingSourceBranch = true; - vm.mr.sourceBranchRemoved = false; - - await nextTick(); - - expect(vm.$el.innerText).toContain('The source branch is being deleted'); - expect(vm.$el.innerText).not.toContain('The source branch has been deleted'); - }); - it('should use mergedEvent mergedAt as tooltip title', () => { expect(vm.$el.querySelector('time').getAttribute('title')).toBe('Jan 24, 2018 1:02pm UTC'); }); diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_merging_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_merging_spec.js index e16c897a49b..49bd3739fdb 100644 --- a/spec/frontend/vue_mr_widget/components/states/mr_widget_merging_spec.js +++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_merging_spec.js @@ -43,19 +43,6 @@ describe('MRWidgetMerging', () => { ).toContain('Merging!'); }); - it('renders branch information', () => { - expect( - wrapper - .find('.mr-info-list') - .text() - .trim() - .replace(/\s\s+/g, ' ') - .replace(/[\r\n]+/g, ' '), - ).toEqual('Merges changes into branch'); - - expect(wrapper.find('a').attributes('href')).toBe('/branch-path'); - }); - describe('initiateMergePolling', () => { it('should call simplePoll', () => { wrapper.vm.initiateMergePolling(); diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js index 3e0840fef4e..4e44ac539f2 100644 --- a/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js +++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js @@ -1,5 +1,4 @@ import { shallowMount } from '@vue/test-utils'; -import statusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue'; import PipelineFailed from '~/vue_merge_request_widget/components/states/pipeline_failed.vue'; describe('PipelineFailed', () => { @@ -9,8 +8,6 @@ describe('PipelineFailed', () => { wrapper = shallowMount(PipelineFailed); }; - const findStatusIcon = () => wrapper.find(statusIcon); - beforeEach(() => { createComponent(); }); @@ -23,8 +20,4 @@ describe('PipelineFailed', () => { it('should render error message with a disabled merge button', () => { expect(wrapper.element).toMatchSnapshot(); }); - - it('merge button should be disabled', () => { - expect(findStatusIcon().props('showDisabledButton')).toBe(true); - }); }); diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js index 188582d2e05..02148e044ec 100644 --- a/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js +++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js @@ -10,7 +10,6 @@ import readyToMergeQuery from 'ee_else_ce/vue_merge_request_widget/queries/state import simplePoll from '~/lib/utils/simple_poll'; import CommitEdit from '~/vue_merge_request_widget/components/states/commit_edit.vue'; import CommitMessageDropdown from '~/vue_merge_request_widget/components/states/commit_message_dropdown.vue'; -import CommitsHeader from '~/vue_merge_request_widget/components/states/commits_header.vue'; import ReadyToMerge from '~/vue_merge_request_widget/components/states/ready_to_merge.vue'; import SquashBeforeMerge from '~/vue_merge_request_widget/components/states/squash_before_merge.vue'; import MergeFailedPipelineConfirmationDialog from '~/vue_merge_request_widget/components/states/merge_failed_pipeline_confirmation_dialog.vue'; @@ -60,6 +59,7 @@ const createTestMr = (customConfig) => { transitionStateMachine: (transition) => eventHub.$emit('StateMachineValueChanged', transition), translateStateToMachine: () => this.transitionStateMachine(), state: 'open', + canMerge: true, }; Object.assign(mr, customConfig.mr); @@ -90,7 +90,7 @@ const createReadyToMergeResponse = (customMr) => { const createComponent = ( customConfig = {}, mergeRequestWidgetGraphql = false, - restructuredMrWidget = false, + restructuredMrWidget = true, ) => { wrapper = shallowMount(ReadyToMerge, { propsData: { @@ -111,7 +111,6 @@ const createComponent = ( }; const findCheckboxElement = () => wrapper.find(SquashBeforeMerge); -const findCommitsHeaderElement = () => wrapper.find(CommitsHeader); const findCommitEditElements = () => wrapper.findAll(CommitEdit); const findCommitDropdownElement = () => wrapper.find(CommitMessageDropdown); const findFirstCommitEditLabel = () => findCommitEditElements().at(0).props('label'); @@ -575,71 +574,9 @@ describe('ReadyToMerge', () => { }); }); - describe('commits count collapsible header', () => { - it('should be rendered when fast-forward is disabled', () => { - createComponent(); - - expect(findCommitsHeaderElement().exists()).toBeTruthy(); - }); - - describe('when fast-forward is enabled', () => { - it('should be rendered if squash and squash before are enabled and there is more than 1 commit', () => { - createComponent({ - mr: { - ffOnlyEnabled: true, - enableSquashBeforeMerge: true, - squashIsSelected: true, - commitsCount: 2, - }, - }); - - expect(findCommitsHeaderElement().exists()).toBeTruthy(); - }); - - it('should not be rendered if squash before merge is disabled', () => { - createComponent({ - mr: { - ffOnlyEnabled: true, - enableSquashBeforeMerge: false, - squash: true, - commitsCount: 2, - }, - }); - - expect(findCommitsHeaderElement().exists()).toBeFalsy(); - }); - - it('should not be rendered if squash is disabled', () => { - createComponent({ - mr: { - ffOnlyEnabled: true, - squash: false, - enableSquashBeforeMerge: true, - commitsCount: 2, - }, - }); - - expect(findCommitsHeaderElement().exists()).toBeFalsy(); - }); - - it('should not be rendered if commits count is 1', () => { - createComponent({ - mr: { - ffOnlyEnabled: true, - squash: true, - enableSquashBeforeMerge: true, - commitsCount: 1, - }, - }); - - expect(findCommitsHeaderElement().exists()).toBeFalsy(); - }); - }); - }); - describe('commits edit components', () => { describe('when fast-forward merge is enabled', () => { - it('should not be rendered if squash is disabled', () => { + it('should not be rendered if squash is disabled', async () => { createComponent({ mr: { ffOnlyEnabled: true, @@ -678,7 +615,7 @@ describe('ReadyToMerge', () => { expect(findCommitEditElements().length).toBe(0); }); - it('should have one edit component if squash is enabled and there is more than 1 commit', () => { + it('should have one edit component if squash is enabled and there is more than 1 commit', async () => { createComponent({ mr: { ffOnlyEnabled: true, @@ -688,18 +625,14 @@ describe('ReadyToMerge', () => { }, }); + await wrapper.find('[data-testid="widget_edit_commit_message"]').vm.$emit('input', true); + expect(findCommitEditElements().length).toBe(1); expect(findFirstCommitEditLabel()).toBe('Squash commit message'); }); }); - it('should have one edit component when squash is disabled', () => { - createComponent(); - - expect(findCommitEditElements().length).toBe(1); - }); - - it('should have two edit components when squash is enabled and there is more than 1 commit', () => { + it('should have two edit components when squash is enabled and there is more than 1 commit', async () => { createComponent({ mr: { commitsCount: 2, @@ -708,6 +641,8 @@ describe('ReadyToMerge', () => { }, }); + await wrapper.find('[data-testid="widget_edit_commit_message"]').vm.$emit('input', true); + expect(findCommitEditElements().length).toBe(2); }); @@ -737,11 +672,12 @@ describe('ReadyToMerge', () => { }, }); await nextTick(); + await wrapper.find('[data-testid="widget_edit_commit_message"]').vm.$emit('input', true); expect(findCommitEditElements().length).toBe(2); }); - it('should have one edit components when squash is enabled and there is 1 commit only', () => { + it('should have one edit components when squash is enabled and there is 1 commit only', async () => { createComponent({ mr: { commitsCount: 1, @@ -750,16 +686,12 @@ describe('ReadyToMerge', () => { }, }); - expect(findCommitEditElements().length).toBe(1); - }); + await wrapper.find('[data-testid="widget_edit_commit_message"]').vm.$emit('input', true); - it('should have correct edit merge commit label', () => { - createComponent(); - - expect(findFirstCommitEditLabel()).toBe('Merge commit message'); + expect(findCommitEditElements().length).toBe(1); }); - it('should have correct edit squash commit label', () => { + it('should have correct edit squash commit label', async () => { createComponent({ mr: { commitsCount: 2, @@ -768,6 +700,8 @@ describe('ReadyToMerge', () => { }, }); + await wrapper.find('[data-testid="widget_edit_commit_message"]').vm.$emit('input', true); + expect(findFirstCommitEditLabel()).toBe('Squash commit message'); }); }); @@ -779,45 +713,23 @@ describe('ReadyToMerge', () => { expect(findCommitDropdownElement().exists()).toBeFalsy(); }); - it('should be rendered if squash is enabled and there is more than 1 commit', () => { + it('should be rendered if squash is enabled and there is more than 1 commit', async () => { createComponent({ mr: { enableSquashBeforeMerge: true, squashIsSelected: true, commitsCount: 2 }, }); + await wrapper.find('[data-testid="widget_edit_commit_message"]').vm.$emit('input', true); + expect(findCommitDropdownElement().exists()).toBeTruthy(); }); }); - it('renders a tip including a link to docs on templates', () => { + it('renders a tip including a link to docs on templates', async () => { createComponent(); - expect(findTipLink().exists()).toBe(true); - }); - }); - - describe('Merge request project settings', () => { - describe('when the merge commit merge method is enabled', () => { - beforeEach(() => { - createComponent({ - mr: { ffOnlyEnabled: false }, - }); - }); - - it('should not show fast forward message', () => { - expect(wrapper.find('.mr-fast-forward-message').exists()).toBe(false); - }); - }); - - describe('when the fast-forward merge method is enabled', () => { - beforeEach(() => { - createComponent({ - mr: { ffOnlyEnabled: true }, - }); - }); + await wrapper.find('[data-testid="widget_edit_commit_message"]').vm.$emit('input', true); - it('should show fast forward message', () => { - expect(wrapper.find('.mr-fast-forward-message').exists()).toBe(true); - }); + expect(findTipLink().exists()).toBe(true); }); }); @@ -872,6 +784,7 @@ describe('ReadyToMerge', () => { createDefaultGqlComponent(); await waitForPromises(); + await wrapper.find('[data-testid="widget_edit_commit_message"]').vm.$emit('input', true); expect(finderFn()).toBe(initialValue); }); @@ -879,6 +792,7 @@ describe('ReadyToMerge', () => { it('should have updated value after graphql refetch', async () => { createDefaultGqlComponent(); await waitForPromises(); + await wrapper.find('[data-testid="widget_edit_commit_message"]').vm.$emit('input', true); triggerApprovalUpdated(); await waitForPromises(); @@ -889,6 +803,7 @@ describe('ReadyToMerge', () => { it('should not update if user has touched', async () => { createDefaultGqlComponent(); await waitForPromises(); + await wrapper.find('[data-testid="widget_edit_commit_message"]').vm.$emit('input', true); const input = wrapper.find(inputId); input.element.value = USER_COMMIT_MESSAGE; diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js index 4998147c6b6..e4ffa37a84d 100644 --- a/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js +++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js @@ -85,8 +85,6 @@ describe('Wip', () => { expect(el.innerText).toContain( "Merge blocked: merge request must be marked as ready. It's still marked as draft.", ); - expect(el.querySelector('button').getAttribute('disabled')).toBeTruthy(); - expect(el.querySelector('button').innerText).toContain('Merge'); expect(el.querySelector('.js-remove-draft').innerText.replace(/\s\s+/g, ' ')).toContain( 'Mark as ready', ); diff --git a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js index b3af5eba364..8367dc6b716 100644 --- a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js +++ b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js @@ -20,7 +20,6 @@ import { import { SUCCESS } from '~/vue_merge_request_widget/components/deployment/constants'; import eventHub from '~/vue_merge_request_widget/event_hub'; import MrWidgetOptions from '~/vue_merge_request_widget/mr_widget_options.vue'; -import { stateKey } from '~/vue_merge_request_widget/stores/state_maps'; import StatusIcon from '~/vue_merge_request_widget/components/extensions/status_icon.vue'; import securityReportMergeRequestDownloadPathsQuery from '~/vue_shared/security_reports/graphql/queries/security_report_merge_request_download_paths.query.graphql'; import { faviconDataUrl, overlayDataUrl } from '../lib/utils/mock_data'; @@ -135,18 +134,6 @@ describe('MrWidgetOptions', () => { }); }); - describe('shouldRenderRelatedLinks', () => { - it('should return false for the initial data', () => { - expect(wrapper.vm.shouldRenderRelatedLinks).toBeFalsy(); - }); - - it('should return true if there is relatedLinks in MR', () => { - Vue.set(wrapper.vm.mr, 'relatedLinks', {}); - - expect(wrapper.vm.shouldRenderRelatedLinks).toBeTruthy(); - }); - }); - describe('shouldRenderSourceBranchRemovalStatus', () => { beforeEach(() => { wrapper.vm.mr.state = 'readyToMerge'; @@ -519,61 +506,6 @@ describe('MrWidgetOptions', () => { }); }); - describe('rendering relatedLinks', () => { - beforeEach(() => { - return createComponent({ - ...mockData, - issues_links: { - closing: ` - <a class="close-related-link" href="#"> - Close - </a> - `, - }, - }); - }); - - afterEach(() => { - wrapper.destroy(); - }); - - it('renders if there are relatedLinks', () => { - expect(wrapper.find('.close-related-link').exists()).toBe(true); - }); - - it('does not render if state is nothingToMerge', async () => { - wrapper.vm.mr.state = stateKey.nothingToMerge; - await nextTick(); - expect(wrapper.find('.close-related-link').exists()).toBe(false); - }); - }); - - describe('rendering source branch removal status', () => { - it('renders when user cannot remove branch and branch should be removed', async () => { - wrapper.vm.mr.canRemoveSourceBranch = false; - wrapper.vm.mr.shouldRemoveSourceBranch = true; - wrapper.vm.mr.state = 'readyToMerge'; - - await nextTick(); - const tooltip = wrapper.find('[data-testid="question-o-icon"]'); - - expect(wrapper.text()).toContain('Deletes the source branch'); - expect(tooltip.attributes('title')).toBe( - 'A user with write access to the source branch selected this option', - ); - }); - - it('does not render in merged state', async () => { - wrapper.vm.mr.canRemoveSourceBranch = false; - wrapper.vm.mr.shouldRemoveSourceBranch = true; - wrapper.vm.mr.state = 'merged'; - - await nextTick(); - expect(wrapper.text()).toContain('The source branch has been deleted'); - expect(wrapper.text()).not.toContain('Deletes the source branch'); - }); - }); - describe('rendering deployments', () => { const changes = [ { @@ -1062,7 +994,7 @@ describe('MrWidgetOptions', () => { await createComponent(); - expect(pollRequest).toHaveBeenCalledTimes(6); + expect(pollRequest).toHaveBeenCalledTimes(4); }); }); @@ -1100,14 +1032,14 @@ describe('MrWidgetOptions', () => { registerExtension(pollingErrorExtension); await createComponent(); - expect(pollRequest).toHaveBeenCalledTimes(6); + expect(pollRequest).toHaveBeenCalledTimes(4); }); it('captures sentry error and displays error when poll has failed', async () => { registerExtension(pollingErrorExtension); await createComponent(); - expect(Sentry.captureException).toHaveBeenCalledTimes(5); + expect(Sentry.captureException).toHaveBeenCalled(); expect(Sentry.captureException).toHaveBeenCalledWith(new Error('Fetch error')); expect(wrapper.findComponent(StatusIcon).props('iconName')).toBe('failed'); }); @@ -1126,7 +1058,7 @@ describe('MrWidgetOptions', () => { expect( wrapper.find('[data-testid="widget-extension"] [data-testid="toggle-button"]').exists(), ).toBe(false); - expect(Sentry.captureException).toHaveBeenCalledTimes(5); + expect(Sentry.captureException).toHaveBeenCalled(); expect(Sentry.captureException).toHaveBeenCalledWith(new Error('Fetch error')); expect(wrapper.findComponent(StatusIcon).props('iconName')).toBe('failed'); }); diff --git a/spec/frontend/vue_mr_widget/stores/get_state_key_spec.js b/spec/frontend/vue_mr_widget/stores/get_state_key_spec.js index fc760f5c5be..0246a8d4b0f 100644 --- a/spec/frontend/vue_mr_widget/stores/get_state_key_spec.js +++ b/spec/frontend/vue_mr_widget/stores/get_state_key_spec.js @@ -25,10 +25,6 @@ describe('getStateKey', () => { expect(bound()).toEqual('readyToMerge'); - context.canMerge = false; - - expect(bound()).toEqual('notAllowedToMerge'); - context.autoMergeEnabled = true; context.hasMergeableDiscussionsState = true; @@ -105,22 +101,4 @@ describe('getStateKey', () => { expect(bound()).toEqual('rebase'); }); - - it.each` - canMerge | isSHAMismatch | stateKey - ${true} | ${true} | ${'shaMismatch'} - ${false} | ${true} | ${'notAllowedToMerge'} - ${false} | ${false} | ${'notAllowedToMerge'} - `( - 'returns $stateKey when canMerge is $canMerge and isSHAMismatch is $isSHAMismatch', - ({ canMerge, isSHAMismatch, stateKey }) => { - const bound = getStateKey.bind({ - canMerge, - isSHAMismatch, - commitsCount: 2, - }); - - expect(bound()).toEqual(stateKey); - }, - ); }); diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index 31a5bc737ba..8577cad1011 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -153,11 +153,6 @@ RSpec.describe Gitlab::GitAccess, :aggregate_failures do end it 'logs' do - allow(Gitlab::AppJsonLogger).to receive(:info).with( - hash_including( - "class" => "AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker" - ) - ) expect(Gitlab::AppJsonLogger).to receive(:info).with( message: 'Actor was :ci', project_id: project.id @@ -751,11 +746,6 @@ RSpec.describe Gitlab::GitAccess, :aggregate_failures do it 'logs' do expect(Gitlab::AppJsonLogger).to receive(:info).with( - hash_including( - "class" => "AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker" - ) - ).once - expect(Gitlab::AppJsonLogger).to receive(:info).with( message: 'Actor was :ci', project_id: project.id ).once diff --git a/spec/lib/gitlab/memory/reports_daemon_spec.rb b/spec/lib/gitlab/memory/reports_daemon_spec.rb index feac5e2bfb2..75334834c5b 100644 --- a/spec/lib/gitlab/memory/reports_daemon_spec.rb +++ b/spec/lib/gitlab/memory/reports_daemon_spec.rb @@ -36,14 +36,14 @@ RSpec.describe Gitlab::Memory::ReportsDaemon do message: 'finished', pid: Process.pid, worker_id: 'worker_1', - report: 'jemalloc_stats' + perf_report: 'jemalloc_stats' )).twice daemon.send(:run_thread) end it 'sets real time duration gauge' do - expect(report_duration_counter).to receive(:increment).with({ report: 'jemalloc_stats' }, an_instance_of(Integer)) + expect(report_duration_counter).to receive(:increment).with({ report: 'jemalloc_stats' }, an_instance_of(Float)) daemon.send(:run_thread) end diff --git a/spec/serializers/issue_entity_spec.rb b/spec/serializers/issue_entity_spec.rb index 6b9c703c627..9335ca61b7d 100644 --- a/spec/serializers/issue_entity_spec.rb +++ b/spec/serializers/issue_entity_spec.rb @@ -39,6 +39,13 @@ RSpec.describe IssueEntity do expect(subject).to include(:time_estimate, :total_time_spent, :human_time_estimate, :human_total_time_spent) end + describe 'current_user' do + it 'has the exprected permissions' do + expect(subject[:current_user]).to include(:can_create_note, :can_update, :can_set_issue_metadata, + :can_award_emoji) + end + end + context 'when issue got moved' do let(:public_project) { create(:project, :public) } let(:member) { create(:user) } diff --git a/spec/services/ci/register_job_service_spec.rb b/spec/services/ci/register_job_service_spec.rb index 2316575f164..5daaa1d39cb 100644 --- a/spec/services/ci/register_job_service_spec.rb +++ b/spec/services/ci/register_job_service_spec.rb @@ -129,6 +129,12 @@ module Ci let!(:build2_project2) { create(:ci_build, :pending, :queued, pipeline: pipeline2) } let!(:build1_project3) { create(:ci_build, :pending, :queued, pipeline: pipeline3) } + it 'picks builds one-by-one' do + expect(Ci::Build).to receive(:find).with(pending_job.id).and_call_original + + expect(execute(shared_runner)).to eq(build1_project1) + end + context 'when using fair scheduling' do context 'when all builds are pending' do it 'prefers projects without builds first' do @@ -739,16 +745,6 @@ module Ci end end - context 'when a long queue is created' do - it 'picks builds one-by-one' do - expect(Ci::Build).to receive(:find).with(pending_job.id).and_call_original - - expect(execute(specific_runner)).to eq(pending_job) - end - - include_examples 'handles runner assignment' - end - context 'when using pending builds table' do include_examples 'handles runner assignment' diff --git a/spec/services/merge_requests/reload_diffs_service_spec.rb b/spec/services/merge_requests/reload_diffs_service_spec.rb index 3d5b65207e6..ed89a02b570 100644 --- a/spec/services/merge_requests/reload_diffs_service_spec.rb +++ b/spec/services/merge_requests/reload_diffs_service_spec.rb @@ -34,7 +34,10 @@ RSpec.describe MergeRequests::ReloadDiffsService, :use_clean_rails_memory_store_ context 'cache clearing' do it 'clears the cache for older diffs on the merge request' do - expect_any_instance_of(Redis).to receive(:del).once.and_call_original + redis = instance_double(Redis) + expect(Gitlab::Redis::Cache).to receive(:with).and_yield(redis) + + expect(redis).to receive(:del).once expect(Rails.cache).to receive(:delete).once.and_call_original subject.execute diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 47cd78873f8..921d6503099 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -208,6 +208,7 @@ RSpec.configure do |config| include StubFeatureFlags include StubSnowplow + include StubMember if ENV['CI'] || ENV['RETRIES'] # This includes the first try, i.e. tests will be run 4 times before failing. diff --git a/spec/support/helpers/stub_member.rb b/spec/support/helpers/stub_member.rb new file mode 100644 index 00000000000..b8fb7bce234 --- /dev/null +++ b/spec/support/helpers/stub_member.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +module StubMember + def self.included(base) + GroupMember.prepend(StubbedMember::GroupMember) + ProjectMember.prepend(StubbedMember::ProjectMember) + end +end diff --git a/spec/support/helpers/stubbed_member.rb b/spec/support/helpers/stubbed_member.rb new file mode 100644 index 00000000000..bf700229656 --- /dev/null +++ b/spec/support/helpers/stubbed_member.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +# Extend the ProjectMember & GroupMember class with the ability to +# to run project_authorizations refresh jobs inline. + +# This is needed so that calls like `group.add_member(user)` or `create(:project_member)` +# in the specs can be run without including `:sidekiq_inline` trait. +module StubbedMember + extend ActiveSupport::Concern + + module ClearDeduplicationData + private + + def clear_deduplication_data! + Gitlab::Redis::Queues.with do |redis| + redis.scan_each(match: '*duplicate*').each do |key| + redis.del(key) + end + end + end + end + + module GroupMember + include ClearDeduplicationData + + private + + def refresh_member_authorized_projects(blocking:) + return super unless blocking + + # First, we remove all the keys associated with deduplication from Redis. + # We can't perform a full flush with `Gitlab::Redis::Queues.with(&:flushdb)` + # because that is going to remove other, unrelated enqueued jobs as well, + # and that is going to fail some specs. + clear_deduplication_data! + + # then we run `super`, which will enqueue a project authorizations refresh job + super + + # then we drain (run) the jobs that were enqueued, but only for the worker class we are interested in. + AuthorizedProjectsWorker.drain + ensure + clear_deduplication_data! + end + end + + module ProjectMember + include ClearDeduplicationData + + private + + def refresh_member_authorized_projects(blocking:) + return super unless blocking + + clear_deduplication_data! + + super + + AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker.drain + ensure + clear_deduplication_data! + end + end +end diff --git a/spec/workers/concerns/waitable_worker_spec.rb b/spec/workers/concerns/waitable_worker_spec.rb index f6d4cc4679d..bf156c3b8cb 100644 --- a/spec/workers/concerns/waitable_worker_spec.rb +++ b/spec/workers/concerns/waitable_worker_spec.rb @@ -30,19 +30,33 @@ RSpec.describe WaitableWorker do describe '.bulk_perform_and_wait' do context '1 job' do - it 'inlines the job' do - args_list = [[1]] - expect(worker).to receive(:bulk_perform_inline).with(args_list).and_call_original - expect(Gitlab::AppJsonLogger).to( - receive(:info).with(a_hash_including('message' => 'running inline', - 'class' => 'Gitlab::Foo::Bar::DummyWorker', - 'job_status' => 'running', - 'queue' => 'foo_bar_dummy')) - .once) - - worker.bulk_perform_and_wait(args_list) - - expect(worker.counter).to eq(1) + it 'runs the jobs asynchronously' do + arguments = [[1]] + + expect(worker).to receive(:bulk_perform_async).with(arguments) + + worker.bulk_perform_and_wait(arguments) + end + + context 'when the feature flag `always_async_project_authorizations_refresh` is turned off' do + before do + stub_feature_flags(always_async_project_authorizations_refresh: false) + end + + it 'inlines the job' do + args_list = [[1]] + expect(worker).to receive(:bulk_perform_inline).with(args_list).and_call_original + expect(Gitlab::AppJsonLogger).to( + receive(:info).with(a_hash_including('message' => 'running inline', + 'class' => 'Gitlab::Foo::Bar::DummyWorker', + 'job_status' => 'running', + 'queue' => 'foo_bar_dummy')) + .once) + + worker.bulk_perform_and_wait(args_list) + + expect(worker.counter).to eq(1) + end end end |