Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
		
							parent
							
								
									997a0743bd
								
							
						
					
					
						commit
						5fd38b5f78
					
				|  | @ -1,6 +1,7 @@ | |||
| mutation issueSetLabels($input: UpdateIssueInput!) { | ||||
|   updateIssue(input: $input) { | ||||
|     issue { | ||||
|       id | ||||
|       labels { | ||||
|         nodes { | ||||
|           id | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| <script> | ||||
| import todoMarkDoneMutation from '~/graphql_shared/mutations/todo_mark_done.mutation.graphql'; | ||||
| import TodoButton from '~/vue_shared/components/todo_button.vue'; | ||||
| import TodoButton from '~/vue_shared/components/sidebar/todo_button.vue'; | ||||
| import createDesignTodoMutation from '../graphql/mutations/create_design_todo.mutation.graphql'; | ||||
| import getDesignQuery from '../graphql/queries/get_design.query.graphql'; | ||||
| import allVersionsMixin from '../mixins/all_versions'; | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ import { __ } from '~/locale'; | |||
| import blobInfoQuery from '../queries/blob_info.query.graphql'; | ||||
| import BlobButtonGroup from './blob_button_group.vue'; | ||||
| import BlobEdit from './blob_edit.vue'; | ||||
| import { loadViewer } from './blob_viewers'; | ||||
| 
 | ||||
| export default { | ||||
|   components: { | ||||
|  | @ -30,7 +31,7 @@ export default { | |||
|         }; | ||||
|       }, | ||||
|       result() { | ||||
|         if (this.hasRichViewer) { | ||||
|         if (this.hasRichViewer && !this.blobViewer) { | ||||
|           this.loadLegacyViewer(); | ||||
|         } | ||||
|         this.switchViewer( | ||||
|  | @ -118,6 +119,10 @@ export default { | |||
|     hasRenderError() { | ||||
|       return Boolean(this.viewer.renderError); | ||||
|     }, | ||||
|     blobViewer() { | ||||
|       const { fileType } = this.viewer; | ||||
|       return loadViewer(fileType); | ||||
|     }, | ||||
|   }, | ||||
|   methods: { | ||||
|     loadLegacyViewer() { | ||||
|  | @ -168,6 +173,7 @@ export default { | |||
|         </template> | ||||
|       </blob-header> | ||||
|       <blob-content | ||||
|         v-if="!blobViewer" | ||||
|         :rich-viewer="legacyRichViewer" | ||||
|         :blob="blobInfo" | ||||
|         :content="blobInfo.rawTextBlob" | ||||
|  | @ -175,6 +181,7 @@ export default { | |||
|         :active-viewer="viewer" | ||||
|         :loading="false" | ||||
|       /> | ||||
|       <component :is="blobViewer" v-else class="blob-viewer" /> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
|  |  | |||
|  | @ -0,0 +1,15 @@ | |||
| export const loadViewer = (type) => { | ||||
|   switch (type) { | ||||
|     case 'empty': | ||||
|       // TODO (follow-up): import the empty viewer
 | ||||
|       return null; // () => import(/* webpackChunkName: 'blob_empty_viewer' */ './empty_viewer.vue');
 | ||||
|     case 'text': | ||||
|       // TODO (follow-up): import the text viewer
 | ||||
|       return null; // () => import(/* webpackChunkName: 'blob_text_viewer' */ './text_viewer.vue');
 | ||||
|     case 'download': | ||||
|       // TODO (follow-up): import the download viewer
 | ||||
|       return null; // () => import(/* webpackChunkName: 'blob_download_viewer' */ './download_viewer.vue');
 | ||||
|     default: | ||||
|       return null; | ||||
|   } | ||||
| }; | ||||
|  | @ -4,7 +4,7 @@ import { produce } from 'immer'; | |||
| import createFlash from '~/flash'; | ||||
| import { __, sprintf } from '~/locale'; | ||||
| import { todoQueries, TodoMutationTypes, todoMutations } from '~/sidebar/constants'; | ||||
| import TodoButton from '~/vue_shared/components/todo_button.vue'; | ||||
| import TodoButton from '~/vue_shared/components/sidebar/todo_button.vue'; | ||||
| 
 | ||||
| export default { | ||||
|   components: { | ||||
|  |  | |||
|  | @ -1,7 +1,6 @@ | |||
| <script> | ||||
| import { GlLabel } from '@gitlab/ui'; | ||||
| import { mapState } from 'vuex'; | ||||
| 
 | ||||
| import { getIdFromGraphQLId } from '~/graphql_shared/utils'; | ||||
| import { isScopedLabel } from '~/lib/utils/common_utils'; | ||||
| 
 | ||||
| export default { | ||||
|  | @ -14,15 +13,26 @@ export default { | |||
|       required: false, | ||||
|       default: false, | ||||
|     }, | ||||
|     selectedLabels: { | ||||
|       type: Array, | ||||
|       required: true, | ||||
|     }, | ||||
|     allowLabelRemove: { | ||||
|       type: Boolean, | ||||
|       required: true, | ||||
|     }, | ||||
|     allowScopedLabels: { | ||||
|       type: Boolean, | ||||
|       required: true, | ||||
|     }, | ||||
|     labelsFilterBasePath: { | ||||
|       type: String, | ||||
|       required: true, | ||||
|     }, | ||||
|     labelsFilterParam: { | ||||
|       type: String, | ||||
|       required: true, | ||||
|     }, | ||||
|   computed: { | ||||
|     ...mapState([ | ||||
|       'selectedLabels', | ||||
|       'allowLabelRemove', | ||||
|       'allowScopedLabels', | ||||
|       'labelsFilterBasePath', | ||||
|       'labelsFilterParam', | ||||
|     ]), | ||||
|   }, | ||||
|   methods: { | ||||
|     labelFilterUrl(label) { | ||||
|  | @ -33,6 +43,9 @@ export default { | |||
|     scopedLabel(label) { | ||||
|       return this.allowScopedLabels && isScopedLabel(label); | ||||
|     }, | ||||
|     removeLabel(labelId) { | ||||
|       this.$emit('onLabelRemove', getIdFromGraphQLId(labelId)); | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
|  | @ -43,12 +56,14 @@ export default { | |||
|       'has-labels': selectedLabels.length, | ||||
|     }" | ||||
|     class="hide-collapsed value issuable-show-labels js-value" | ||||
|     data-testid="value-wrapper" | ||||
|   > | ||||
|     <span v-if="!selectedLabels.length" class="text-secondary"> | ||||
|     <span v-if="!selectedLabels.length" class="text-secondary" data-testid="empty-placeholder"> | ||||
|       <slot></slot> | ||||
|     </span> | ||||
|     <template v-for="label in selectedLabels" v-else> | ||||
|     <template v-else> | ||||
|       <gl-label | ||||
|         v-for="label in selectedLabels" | ||||
|         :key="label.id" | ||||
|         data-qa-selector="selected_label_content" | ||||
|         :data-qa-label-name="label.title" | ||||
|  | @ -60,7 +75,7 @@ export default { | |||
|         :show-close-button="allowLabelRemove" | ||||
|         :disabled="disableLabels" | ||||
|         tooltip-placement="top" | ||||
|         @close="$emit('onLabelRemove', label.id)" | ||||
|         @close="removeLabel(label.id)" | ||||
|       /> | ||||
|     </template> | ||||
|   </div> | ||||
|  |  | |||
|  | @ -0,0 +1,15 @@ | |||
| query issueLabels($fullPath: ID!, $iid: String) { | ||||
|   workspace: project(fullPath: $fullPath) { | ||||
|     issuable: issue(iid: $iid) { | ||||
|       id | ||||
|       labels { | ||||
|         nodes { | ||||
|           id | ||||
|           title | ||||
|           color | ||||
|           description | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -11,6 +11,7 @@ import DropdownContents from './dropdown_contents.vue'; | |||
| import DropdownTitle from './dropdown_title.vue'; | ||||
| import DropdownValue from './dropdown_value.vue'; | ||||
| import DropdownValueCollapsed from './dropdown_value_collapsed.vue'; | ||||
| import issueLabelsQuery from './graphql/issue_labels.query.graphql'; | ||||
| import labelsSelectModule from './store'; | ||||
| 
 | ||||
| Vue.use(Vuex); | ||||
|  | @ -24,6 +25,7 @@ export default { | |||
|     DropdownContents, | ||||
|     DropdownValueCollapsed, | ||||
|   }, | ||||
|   inject: ['iid', 'projectPath'], | ||||
|   props: { | ||||
|     allowLabelRemove: { | ||||
|       type: Boolean, | ||||
|  | @ -119,8 +121,23 @@ export default { | |||
|   data() { | ||||
|     return { | ||||
|       contentIsOnViewport: true, | ||||
|       issueLabels: [], | ||||
|     }; | ||||
|   }, | ||||
|   apollo: { | ||||
|     issueLabels: { | ||||
|       query: issueLabelsQuery, | ||||
|       variables() { | ||||
|         return { | ||||
|           iid: this.iid, | ||||
|           fullPath: this.projectPath, | ||||
|         }; | ||||
|       }, | ||||
|       update(data) { | ||||
|         return data.workspace?.issuable?.labels.nodes || []; | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['showDropdownButton', 'showDropdownContents']), | ||||
|     ...mapGetters([ | ||||
|  | @ -293,7 +310,7 @@ export default { | |||
|     <template v-if="isDropdownVariantSidebar"> | ||||
|       <dropdown-value-collapsed | ||||
|         ref="dropdownButtonCollapsed" | ||||
|         :labels="selectedLabels" | ||||
|         :labels="issueLabels" | ||||
|         @onValueClick="handleCollapsedValueClick" | ||||
|       /> | ||||
|       <dropdown-title | ||||
|  | @ -302,6 +319,11 @@ export default { | |||
|       /> | ||||
|       <dropdown-value | ||||
|         :disable-labels="labelsSelectInProgress" | ||||
|         :selected-labels="issueLabels" | ||||
|         :allow-label-remove="allowLabelRemove" | ||||
|         :allow-scoped-labels="allowScopedLabels" | ||||
|         :labels-filter-base-path="labelsFilterBasePath" | ||||
|         :labels-filter-param="labelsFilterParam" | ||||
|         @onLabelRemove="$emit('onLabelRemove', $event)" | ||||
|       > | ||||
|         <slot></slot> | ||||
|  |  | |||
|  | @ -8,15 +8,16 @@ | |||
|         .form-check | ||||
|           = f.check_box :repository_checks_enabled, class: 'form-check-input' | ||||
|           = f.label :repository_checks_enabled, class: 'form-check-label' do | ||||
|             = _("Enable Repository Checks") | ||||
|             = _("Enable repository checks") | ||||
|           .form-text.text-muted | ||||
|             - link_to_git_fsck = link_to('git fsck', 'https://git-scm.com/docs/git-fsck', target: '_blank') | ||||
|             = _("GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues.").html_safe % { link_to_git_fsck: link_to_git_fsck } | ||||
|             = _("Run") | ||||
|             %code= _("git fsck") | ||||
|             = _("periodically in all project and wiki repositories to look for silent disk corruption issues.") | ||||
|       .form-group | ||||
|         .form-text.text-muted | ||||
|           = _("If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database.") | ||||
|           = _("If you get a lot of false alarms from repository checks, you can clear all repository check information from the database.") | ||||
|           - clear_repository_checks_link = _('Clear all repository checks') | ||||
|           - clear_repository_checks_message = _('This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?') | ||||
|           - clear_repository_checks_message = _('This clears repository check states for all projects in the database and cannot be undone. Are you sure?') | ||||
|         = link_to clear_repository_checks_link, clear_repository_check_states_admin_application_settings_path, data: { confirm: clear_repository_checks_message }, method: :put, class: "gl-button btn btn-sm btn-danger gl-mt-3" | ||||
| 
 | ||||
|     .sub-section | ||||
|  | @ -25,29 +26,37 @@ | |||
|         .form-check | ||||
|           = f.check_box :housekeeping_enabled, class: 'form-check-input' | ||||
|           = f.label :housekeeping_enabled, class: 'form-check-label' do | ||||
|             = _("Enable automatic repository housekeeping (git repack, git gc)") | ||||
|             = _("Enable automatic repository housekeeping") | ||||
|           .form-text.text-muted | ||||
|             = _("If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled.") | ||||
|             = _("Leaving this setting enabled is recommended.") | ||||
|             = link_to s_('Learn more.'), help_page_path('administration/housekeeping.md', anchor: 'housekeeping-options'), target: '_blank', rel: 'noopener noreferrer' | ||||
|         .form-check | ||||
|           = f.check_box :housekeeping_bitmaps_enabled, class: 'form-check-input' | ||||
|           = f.label :housekeeping_bitmaps_enabled, class: 'form-check-label' do | ||||
|             = _("Enable Git pack file bitmap creation") | ||||
|           .form-text.text-muted | ||||
|             = _("Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance.") | ||||
|             = _("Improves Git cloning performance.") | ||||
|             = link_to s_('Learn more.'), help_page_path('administration/housekeeping.md', anchor: 'housekeeping-options'), target: '_blank', rel: 'noopener noreferrer' | ||||
|       .form-group | ||||
|         = f.label :housekeeping_incremental_repack_period, 'Incremental repack period', class: 'label-bold' | ||||
|         = f.number_field :housekeeping_incremental_repack_period, class: 'form-control gl-form-input' | ||||
|         .form-text.text-muted | ||||
|           = _("Number of Git pushes after which an incremental 'git repack' is run.") | ||||
|           = _("Number of Git pushes after which an incremental") | ||||
|           %code= _("git repack") | ||||
|           = _("is run.") | ||||
|       .form-group | ||||
|         = f.label :housekeeping_full_repack_period, 'Full repack period', class: 'label-bold' | ||||
|         = f.number_field :housekeeping_full_repack_period, class: 'form-control gl-form-input' | ||||
|         .form-text.text-muted | ||||
|           = _("Number of Git pushes after which a full 'git repack' is run.") | ||||
|           = _("Number of Git pushes after which a full") | ||||
|           %code= _("git repack") | ||||
|           = _("is run.") | ||||
|       .form-group | ||||
|         = f.label :housekeeping_gc_period, _('Git GC period'), class: 'label-bold' | ||||
|         = f.number_field :housekeeping_gc_period, class: 'form-control gl-form-input' | ||||
|         .form-text.text-muted | ||||
|           = _("Number of Git pushes after which 'git gc' is run.") | ||||
|           = _("Number of Git pushes after which") | ||||
|           %code= _("git gc") | ||||
|           = _("is run.") | ||||
| 
 | ||||
|   = f.submit _('Save changes'), class: "gl-button btn btn-confirm" | ||||
|  |  | |||
|  | @ -42,7 +42,11 @@ | |||
|     %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' } | ||||
|       = expanded_by_default? ? _('Collapse') : _('Expand') | ||||
|     %p | ||||
|       = _('Configure automatic git checks and housekeeping on repositories.') | ||||
|       = _('Configure') | ||||
|       = link_to s_('repository checks'), help_page_path('administration/repository_checks.md'), target: '_blank', rel: 'noopener noreferrer' | ||||
|       = _('and') | ||||
|       = link_to s_('housekeeping'), help_page_path('administration/housekeeping.md'), target: '_blank', rel: 'noopener noreferrer' | ||||
|       = _('on repositories.') | ||||
|   .settings-content | ||||
|     = render 'repository_check' | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,46 +4,68 @@ group: Distribution | |||
| info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments | ||||
| --- | ||||
| 
 | ||||
| # Housekeeping **(FREE)** | ||||
| # Housekeeping **(FREE SELF)** | ||||
| 
 | ||||
| GitLab supports and automates housekeeping tasks within your current repository, | ||||
| such as compressing file revisions and removing unreachable objects. | ||||
| GitLab supports and automates housekeeping tasks within your current repository such as: | ||||
| 
 | ||||
| - Compressing Git objects. | ||||
| - Removing unreachable objects. | ||||
| 
 | ||||
| ## Configure housekeeping | ||||
| 
 | ||||
| GitLab automatically runs `git gc` and `git repack` on repositories | ||||
| after Git pushes. | ||||
| GitLab automatically runs `git gc` and `git repack` on repositories after Git pushes: | ||||
| 
 | ||||
| - [`git gc`](https://git-scm.com/docs/git-gc) runs a number of housekeeping tasks such as: | ||||
|   - Compressing Git objects to reduce disk space and increase performance. | ||||
|   - Removing unreachable objects that may have been created from changes to the repository, like force-overwriting branches. | ||||
| - [`git repack`](https://git-scm.com/docs/git-repack) either: | ||||
|   - Runs an incremental repack, according to a [configured period](#housekeeping-options). This | ||||
|     packs all loose objects into a new packfile and prunes the now-redundant loose objects. | ||||
|   - Runs a full repack, according to a [configured period](#housekeeping-options). This repacks all | ||||
|     packfiles and loose objects into a single new packfile, and deletes the old now-redundant loose | ||||
|     objects and packfiles. It also optionally creates bitmaps for the new packfile. | ||||
| 
 | ||||
| You can change how often this happens or turn it off: | ||||
| 
 | ||||
| 1. On the top bar, select **Menu >** **{admin}** **Admin**. | ||||
| 1. On the left sidebar, select **Settings > Repository**. | ||||
| 1. Expand **Repository maintenance**. | ||||
| 1. Configure the Housekeeping options. | ||||
| 1. In the **Housekeeping** section, configure the [housekeeping options](#housekeeping-options). | ||||
| 1. Select **Save changes**. | ||||
| 
 | ||||
| For example, in the following scenario a `git repack -d` will be executed: | ||||
| ### Housekeeping options | ||||
| 
 | ||||
| - Project: pushes since GC counter (`pushes_since_gc`) = `10` | ||||
| - Git GC period = `200` | ||||
| - Full repack period = `50` | ||||
| The following housekeeping options are available: | ||||
| 
 | ||||
| When the `pushes_since_gc` value is 50 a `repack -A -d --pack-kept-objects` runs, similarly when | ||||
| the `pushes_since_gc` value is 200 a `git gc` runs: | ||||
| - **Enable automatic repository housekeeping**: Regularly run `git repack` and `git gc`. If you | ||||
|   keep this setting disabled for a long time, Git repository access on your GitLab server becomes | ||||
|   slower and your repositories use more disk space. | ||||
| - **Enable Git pack file bitmap creation**: Create pack file bitmaps which accelerates `git clone` | ||||
|   performance. Makes housekeeping take a little longer. | ||||
| - **Incremental repack period**: Number of Git pushes after which an incremental `git repack` is | ||||
|   run. | ||||
| - **Full repack period**: Number of Git pushes after which a full `git repack` is run. | ||||
| - **Git GC period**: Number of Git pushes after which `git gc` is run. | ||||
| 
 | ||||
| - `git gc` ([man page](https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-gc.html)) runs a number of housekeeping tasks, | ||||
|   such as compressing file revisions (to reduce disk space and increase performance) | ||||
|   and removing unreachable objects which may have been created from prior invocations of | ||||
|   `git add`. | ||||
| - `git repack` ([man page](https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-repack.html)) re-organize existing packs into a single, more efficient pack. | ||||
| As an example, see the following scenario: | ||||
| 
 | ||||
| - Incremental repack period: 10. | ||||
| - Full repack period: 50. | ||||
| - Git GC period: 200. | ||||
| 
 | ||||
| When the: | ||||
| 
 | ||||
| - `pushes_since_gc` value is 50, a `repack -A -l -d --pack-kept-objects` runs. | ||||
| - `pushes_since_gc` value is 200, a `git gc` runs. | ||||
| 
 | ||||
| Housekeeping also [removes unreferenced LFS files](../raketasks/cleanup.md#remove-unreferenced-lfs-files) | ||||
| from your project on the same schedule as the `git gc` operation, freeing up storage space for your project. | ||||
| from your project on the same schedule as the `git gc` operation, freeing up storage space for your | ||||
| project. | ||||
| 
 | ||||
| ## How housekeeping handles pool repositories | ||||
| 
 | ||||
| Housekeeping for pool repositories is handled differently from standard repositories. | ||||
| It is ultimately performed by the Gitaly RPC `FetchIntoObjectPool`. | ||||
| Housekeeping for pool repositories is handled differently from standard repositories. It is | ||||
| ultimately performed by the Gitaly RPC `FetchIntoObjectPool`. | ||||
| 
 | ||||
| This is the current call stack by which it is invoked: | ||||
| 
 | ||||
|  | @ -54,10 +76,10 @@ This is the current call stack by which it is invoked: | |||
| 1. `ObjectPoolService#fetch` | ||||
| 1. `Gitaly::FetchIntoObjectPoolRequest` | ||||
| 
 | ||||
| To manually invoke it from a Rails console, if needed, you can call `project.pool_repository.object_pool.fetch`. | ||||
| This is a potentially long-running task, though Gitaly times out in about 8 hours. | ||||
| To manually invoke it from a Rails console if needed, you can call | ||||
| `project.pool_repository.object_pool.fetch`. This is a potentially long-running task, though Gitaly | ||||
| times out in about 8 hours. | ||||
| 
 | ||||
| WARNING: | ||||
| Do not run `git prune` or `git gc` in pool repositories! This can | ||||
| cause data loss in "real" repositories that depend on the pool in | ||||
| question. | ||||
| Do not run `git prune` or `git gc` in pool repositories! This can cause data loss in "real" | ||||
| repositories that depend on the pool in question. | ||||
|  |  | |||
|  | @ -5,57 +5,64 @@ info: "To determine the technical writer assigned to the Stage/Group associated | |||
| type: reference | ||||
| --- | ||||
| 
 | ||||
| # Repository checks **(FREE)** | ||||
| # Repository checks **(FREE SELF)** | ||||
| 
 | ||||
| > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3232) in GitLab 8.7. | ||||
| You can use [`git fsck`](https://git-scm.com/docs/git-fsck) to verify the integrity of all data | ||||
| committed to a repository. GitLab administrators can trigger this check for a project using the | ||||
| GitLab UI: | ||||
| 
 | ||||
| Git has a built-in mechanism, [`git fsck`](https://git-scm.com/docs/git-fsck), to verify the | ||||
| integrity of all data committed to a repository. GitLab administrators | ||||
| can trigger such a check for a project via the project page under the | ||||
| Admin Area. The checks run asynchronously so it may take a few minutes | ||||
| before the check result is visible on the project Admin Area. If the | ||||
| checks failed you can see their output on in the | ||||
| [`repocheck.log` file.](logs.md#repochecklog) | ||||
| 1. On the top bar, select **Menu >** **{admin}** **Admin**. | ||||
| 1. On the left sidebar, select **Overview > Projects**. | ||||
| 1. Select the project to check. | ||||
| 1. In the **Repository check** section, select **Trigger repository check**. | ||||
| 
 | ||||
| The checks run asynchronously so it may take a few minutes before the check result is visible on the | ||||
| project page in the Admin Area. If the checks fail, see [what to do](#what-to-do-if-a-check-failed). | ||||
| 
 | ||||
| This setting is off by default, because it can cause many false alarms. | ||||
| 
 | ||||
| ## Periodic checks | ||||
| ## Enable periodic checks | ||||
| 
 | ||||
| When enabled, GitLab periodically runs a repository check on all project | ||||
| repositories and wiki repositories in order to detect data corruption. | ||||
| A project is checked no more than once per month. If any projects | ||||
| fail their repository checks all GitLab administrators receive an email | ||||
| notification of the situation. This notification is sent out once a week, | ||||
| by default, midnight at the start of Sunday. Repositories with known check | ||||
| failures can be found at `/admin/projects?last_repository_check_failed=1`. | ||||
| Instead of checking repositories manually, GitLab can be configured to run the checks periodically: | ||||
| 
 | ||||
| ## Disabling periodic checks | ||||
| 1. On the top bar, select **Menu >** **{admin}** **Admin**. | ||||
| 1. On the left sidebar, select **Settings > Repository** (`/admin/application_settings/repository`). | ||||
| 1. Expand the **Repository maintenance** section. | ||||
| 1. Enable **Enable repository checks**. | ||||
| 
 | ||||
| You can disable the periodic checks on the **Settings** page of the Admin Area. | ||||
| When enabled, GitLab periodically runs a repository check on all project repositories and wiki | ||||
| repositories to detect possible data corruption. A project is checked no more than once per month. | ||||
| 
 | ||||
| If any projects fail their repository checks, all GitLab administrators receive an email | ||||
| notification of the situation. By default, this notification is sent out once a week at midnight at | ||||
| the start of Sunday. | ||||
| 
 | ||||
| Repositories with known check failures can be found at | ||||
| `/admin/projects?last_repository_check_failed=1`. | ||||
| 
 | ||||
| ## What to do if a check failed | ||||
| 
 | ||||
| If the repository check fails for some repository you should look up the error | ||||
| in the [`repocheck.log` file](logs.md#repochecklog) on disk: | ||||
| If a repository check fails, locate the error in the [`repocheck.log` file](logs.md#repochecklog) on | ||||
| disk at: | ||||
| 
 | ||||
| - `/var/log/gitlab/gitlab-rails` for Omnibus GitLab installations | ||||
| - `/home/git/gitlab/log` for installations from source | ||||
| - `/var/log/gitlab/gitlab-rails` for Omnibus GitLab installations. | ||||
| - `/home/git/gitlab/log` for installations from source. | ||||
| 
 | ||||
| If the periodic repository check causes false alarms, you can clear all repository check states by: | ||||
| If periodic repository checks cause false alarms, you can clear all repository check states: | ||||
| 
 | ||||
| 1. On the top bar, select **Menu >** **{admin}** **Admin**. | ||||
| 1. On the left sidebar, select **Settings > Repository** (`/admin/application_settings/repository`). | ||||
| 1. Expand the **Repository maintenance** section. | ||||
| 1. Select **Clear all repository checks**. | ||||
| 
 | ||||
| ## Run a check manually | ||||
| ## Run a check using the command line | ||||
| 
 | ||||
| [`git fsck`](https://git-scm.com/docs/git-fsck) is a read-only check that you can run | ||||
| manually against the repository on the [Gitaly server](gitaly/index.md). | ||||
| You can run [`git fsck`](https://git-scm.com/docs/git-fsck) using the command line on repositories | ||||
| on [Gitaly servers](gitaly/index.md). To locate the repositories: | ||||
| 
 | ||||
| - For Omnibus GitLab installations, repositories are stored by default in | ||||
|   `/var/opt/gitlab/git-data/repositories`. | ||||
| - [Identify the subdirectory that contains the repository](repository_storage_types.md#from-project-name-to-hashed-path) | ||||
| 1. Go to the storage location for repositories. For Omnibus GitLab installations, repositories are | ||||
|    stored by default in the `/var/opt/gitlab/git-data/repositories` directory. | ||||
| 1. [Identify the subdirectory that contains the repository](repository_storage_types.md#from-project-name-to-hashed-path) | ||||
|    that you need to check. | ||||
| 
 | ||||
| To run a check (for example): | ||||
|  | @ -65,5 +72,5 @@ sudo /opt/gitlab/embedded/bin/git -C /var/opt/gitlab/git-data/repositories/@hash | |||
| ``` | ||||
| 
 | ||||
| You can also run [Rake tasks](raketasks/check.md#repository-integrity) for checking Git | ||||
| repositories, which can be used to run `git fsck` against all repositories and generate | ||||
| repository checksums, as a way to compare repositories on different servers. | ||||
| repositories, which can be used to run `git fsck` against all repositories and generate repository | ||||
| checksums, as a way to compare repositories on different servers. | ||||
|  |  | |||
|  | @ -111,6 +111,7 @@ https://docs.google.com/drawings/d/1fBzAyklyveF-i-2q-OHUIqDkYfjjxC4mq5shwKSZHLs/ | |||
| ### Component diagram | ||||
| 
 | ||||
| ```mermaid | ||||
| %%{init: {"flowchart": { "useMaxWidth": false } }}%% | ||||
| graph LR | ||||
|   %% Anchor items in the appropriate subgraph. | ||||
|   %% Link them where the destination* is. | ||||
|  |  | |||
|  | @ -38,13 +38,14 @@ To add a story: | |||
|     ```txt | ||||
|     vue_shared/ | ||||
|     ├─ components/ | ||||
|     │  ├─ todo_button.vue | ||||
|     │  ├─ todo_button.stories.js | ||||
|     │  ├─ sidebar | ||||
|     │  │  ├─ todo_button.vue | ||||
|     │  │  ├─ todo_button.stories.js | ||||
|     ``` | ||||
| 
 | ||||
| 1. Write the story as per the [official Storybook instructions](https://storybook.js.org/docs/vue/writing-stories/introduction/) | ||||
| 
 | ||||
|    Notes: | ||||
|    - Specify the `title` field of the story as the component's file path from the `javascripts/` directory, | ||||
|      e.g. if the component is located at `app/assets/javascripts/vue_shared/components/todo_button.vue`, specify the `title` as | ||||
|      e.g. if the component is located at `app/assets/javascripts/vue_shared/components/sidebar/todo_button.vue`, specify the `title` as | ||||
|      `vue_shared/components/To-do Button`. This will ensure the Storybook navigation maps closely to our internal directory structure. | ||||
|  |  | |||
|  | @ -8196,6 +8196,9 @@ msgstr "" | |||
| msgid "Configuration help" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Configure" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Configure %{link} to track events. %{link_start}Learn more.%{link_end}" | ||||
| msgstr "" | ||||
| 
 | ||||
|  | @ -8235,9 +8238,6 @@ msgstr "" | |||
| msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Configure automatic git checks and housekeeping on repositories." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Configure existing installation" | ||||
| msgstr "" | ||||
| 
 | ||||
|  | @ -9495,9 +9495,6 @@ msgstr "" | |||
| msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Creation date" | ||||
| msgstr "" | ||||
| 
 | ||||
|  | @ -12043,9 +12040,6 @@ msgstr "" | |||
| msgid "Enable Registration Features" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Enable Repository Checks" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Enable SSL verification" | ||||
| msgstr "" | ||||
| 
 | ||||
|  | @ -12088,7 +12082,7 @@ msgstr "" | |||
| msgid "Enable authentication" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Enable automatic repository housekeeping (git repack, git gc)" | ||||
| msgid "Enable automatic repository housekeeping" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Enable classification control using an external service" | ||||
|  | @ -12151,6 +12145,9 @@ msgstr "" | |||
| msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Enable repository checks" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Enable service ping" | ||||
| msgstr "" | ||||
| 
 | ||||
|  | @ -14962,9 +14959,6 @@ msgstr "" | |||
| msgid "GitLab will inform you if a new version is available." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory." | ||||
| msgstr "" | ||||
| 
 | ||||
|  | @ -16448,10 +16442,7 @@ msgstr "" | |||
| msgid "If you did not recently sign in, you should immediately change your password: %{password_link}." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled." | ||||
| msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes." | ||||
|  | @ -16685,6 +16676,9 @@ msgstr "" | |||
| msgid "Improve search with Advanced Search and GitLab Enterprise Edition." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Improves Git cloning performance." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "In %{time_to_now}" | ||||
| msgstr "" | ||||
| 
 | ||||
|  | @ -19338,6 +19332,9 @@ msgstr "" | |||
| msgid "Leave zen mode" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Leaving this setting enabled is recommended." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Legacy burndown chart" | ||||
| msgstr "" | ||||
| 
 | ||||
|  | @ -22545,13 +22542,13 @@ msgstr "" | |||
| msgid "Number of Elasticsearch shards and replicas (per index)" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Number of Git pushes after which 'git gc' is run." | ||||
| msgid "Number of Git pushes after which" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Number of Git pushes after which a full 'git repack' is run." | ||||
| msgid "Number of Git pushes after which a full" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Number of Git pushes after which an incremental 'git repack' is run." | ||||
| msgid "Number of Git pushes after which an incremental" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Number of LOCs per commit" | ||||
|  | @ -28045,6 +28042,9 @@ msgstr "" | |||
| msgid "Rules that define what git pushes are accepted for a project. All newly created projects will use these settings." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Run" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Run CI/CD pipelines for external repositories" | ||||
| msgstr "" | ||||
| 
 | ||||
|  | @ -33162,6 +33162,9 @@ msgstr "" | |||
| msgid "This chart could not be displayed" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "This clears repository check states for all projects in the database and cannot be undone. Are you sure?" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "This code snippet contains everything reflected in the configuration form. Copy and paste it into %{linkStart}.gitlab-ci.yml%{linkEnd} file and save your changes. Future %{scanType} scans will use these settings." | ||||
| msgstr "" | ||||
| 
 | ||||
|  | @ -33588,9 +33591,6 @@ msgstr "" | |||
| msgid "This variable can not be masked." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "This will redirect you to an external sign in page." | ||||
| msgstr "" | ||||
| 
 | ||||
|  | @ -38609,6 +38609,15 @@ msgid_plural "from %d jobs" | |||
| msgstr[0] "" | ||||
| msgstr[1] "" | ||||
| 
 | ||||
| msgid "git fsck" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "git gc" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "git repack" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "group" | ||||
| msgstr "" | ||||
| 
 | ||||
|  | @ -38642,6 +38651,9 @@ msgstr "" | |||
| msgid "here" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "housekeeping" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "http:" | ||||
| msgstr "" | ||||
| 
 | ||||
|  | @ -38737,6 +38749,9 @@ msgstr "" | |||
| msgid "is read-only" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "is run." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "is too long (%{current_value}). The maximum size is %{max_size}." | ||||
| msgstr "" | ||||
| 
 | ||||
|  | @ -39237,6 +39252,9 @@ msgstr "" | |||
| msgid "nounSeries|%{item}, and %{lastItem}" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "on repositories." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "on track" | ||||
| msgstr "" | ||||
| 
 | ||||
|  | @ -39280,6 +39298,9 @@ msgstr "" | |||
| msgid "per day" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "periodically in all project and wiki repositories to look for silent disk corruption issues." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "personal access token" | ||||
| msgstr "" | ||||
| 
 | ||||
|  | @ -39385,6 +39406,9 @@ msgid_plural "replies" | |||
| msgstr[0] "" | ||||
| msgstr[1] "" | ||||
| 
 | ||||
| msgid "repository checks" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "repository:" | ||||
| msgstr "" | ||||
| 
 | ||||
|  |  | |||
|  | @ -38,6 +38,7 @@ module QA | |||
|             set_path(full_path, name) | ||||
|             import_project(full_path) | ||||
|             wait_for_success | ||||
|             go_to_project(name) | ||||
|           end | ||||
| 
 | ||||
|           private | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ import { shallowMount, mount } from '@vue/test-utils'; | |||
| import DesignTodoButton from '~/design_management/components/design_todo_button.vue'; | ||||
| import createDesignTodoMutation from '~/design_management/graphql/mutations/create_design_todo.mutation.graphql'; | ||||
| import todoMarkDoneMutation from '~/graphql_shared/mutations/todo_mark_done.mutation.graphql'; | ||||
| import TodoButton from '~/vue_shared/components/todo_button.vue'; | ||||
| import TodoButton from '~/vue_shared/components/sidebar/todo_button.vue'; | ||||
| import mockDesign from '../mock_data/design'; | ||||
| 
 | ||||
| const mockDesignWithPendingTodos = { | ||||
|  |  | |||
|  | @ -11,8 +11,11 @@ import BlobHeader from '~/blob/components/blob_header.vue'; | |||
| import BlobButtonGroup from '~/repository/components/blob_button_group.vue'; | ||||
| import BlobContentViewer from '~/repository/components/blob_content_viewer.vue'; | ||||
| import BlobEdit from '~/repository/components/blob_edit.vue'; | ||||
| import { loadViewer } from '~/repository/components/blob_viewers'; | ||||
| import blobInfoQuery from '~/repository/queries/blob_info.query.graphql'; | ||||
| 
 | ||||
| jest.mock('~/repository/components/blob_viewers'); | ||||
| 
 | ||||
| let wrapper; | ||||
| const simpleMockData = { | ||||
|   name: 'some_file.js', | ||||
|  | @ -208,6 +211,19 @@ describe('Blob content viewer component', () => { | |||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe('Blob viewer', () => { | ||||
|     beforeEach(() => { | ||||
|       loadViewer.mockClear(); | ||||
|     }); | ||||
| 
 | ||||
|     it('does not render a BlobContent component if a Blob viewer is available', () => { | ||||
|       loadViewer.mockReturnValueOnce(() => true); | ||||
|       factory({ mockData: { blobInfo: richMockData } }); | ||||
| 
 | ||||
|       expect(findBlobContent().exists()).toBe(false); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe('BlobHeader action slot', () => { | ||||
|     const { ideEditPath, editBlobPath } = simpleMockData; | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ import waitForPromises from 'helpers/wait_for_promises'; | |||
| import createFlash from '~/flash'; | ||||
| import SidebarTodoWidget from '~/sidebar/components/todo_toggle/sidebar_todo_widget.vue'; | ||||
| import epicTodoQuery from '~/sidebar/queries/epic_todo.query.graphql'; | ||||
| import TodoButton from '~/vue_shared/components/todo_button.vue'; | ||||
| import TodoButton from '~/vue_shared/components/sidebar/todo_button.vue'; | ||||
| import { todosResponse, noTodosResponse } from '../../mock_data'; | ||||
| 
 | ||||
| jest.mock('~/flash'); | ||||
|  |  | |||
|  | @ -1,70 +1,39 @@ | |||
| import { GlLabel } from '@gitlab/ui'; | ||||
| import { shallowMount, createLocalVue } from '@vue/test-utils'; | ||||
| import Vuex from 'vuex'; | ||||
| import { shallowMount } from '@vue/test-utils'; | ||||
| 
 | ||||
| import DropdownValue from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue'; | ||||
| 
 | ||||
| import labelsSelectModule from '~/vue_shared/components/sidebar/labels_select_widget/store'; | ||||
| 
 | ||||
| import { mockConfig, mockRegularLabel, mockScopedLabel } from './mock_data'; | ||||
| 
 | ||||
| const localVue = createLocalVue(); | ||||
| localVue.use(Vuex); | ||||
| import { mockRegularLabel, mockScopedLabel } from './mock_data'; | ||||
| 
 | ||||
| describe('DropdownValue', () => { | ||||
|   let wrapper; | ||||
| 
 | ||||
|   const createComponent = (initialState = {}, slots = {}) => { | ||||
|     const store = new Vuex.Store(labelsSelectModule()); | ||||
| 
 | ||||
|     store.dispatch('setInitialState', { ...mockConfig, ...initialState }); | ||||
|   const findAllLabels = () => wrapper.findAllComponents(GlLabel); | ||||
|   const findRegularLabel = () => findAllLabels().at(0); | ||||
|   const findScopedLabel = () => findAllLabels().at(1); | ||||
|   const findWrapper = () => wrapper.find('[data-testid="value-wrapper"]'); | ||||
|   const findEmptyPlaceholder = () => wrapper.find('[data-testid="empty-placeholder"]'); | ||||
| 
 | ||||
|   const createComponent = (props = {}, slots = {}) => { | ||||
|     wrapper = shallowMount(DropdownValue, { | ||||
|       localVue, | ||||
|       store, | ||||
|       slots, | ||||
|       propsData: { | ||||
|         selectedLabels: [mockRegularLabel, mockScopedLabel], | ||||
|         allowLabelRemove: true, | ||||
|         allowScopedLabels: true, | ||||
|         labelsFilterBasePath: '/gitlab-org/my-project/issues', | ||||
|         labelsFilterParam: 'label_name', | ||||
|         ...props, | ||||
|       }, | ||||
|     }); | ||||
|   }; | ||||
| 
 | ||||
|   afterEach(() => { | ||||
|     wrapper.destroy(); | ||||
|     wrapper = null; | ||||
|   }); | ||||
| 
 | ||||
|   describe('methods', () => { | ||||
|     describe('labelFilterUrl', () => { | ||||
|       it('returns a label filter URL based on provided label param', () => { | ||||
|         createComponent(); | ||||
| 
 | ||||
|         expect(wrapper.vm.labelFilterUrl(mockRegularLabel)).toBe( | ||||
|           '/gitlab-org/my-project/issues?label_name[]=Foo%20Label', | ||||
|         ); | ||||
|       }); | ||||
|     }); | ||||
| 
 | ||||
|     describe('scopedLabel', () => { | ||||
|   describe('when there are no labels', () => { | ||||
|     beforeEach(() => { | ||||
|         createComponent(); | ||||
|       }); | ||||
| 
 | ||||
|       it('returns `true` when provided label param is a scoped label', () => { | ||||
|         expect(wrapper.vm.scopedLabel(mockScopedLabel)).toBe(true); | ||||
|       }); | ||||
| 
 | ||||
|       it('returns `false` when provided label param is a regular label', () => { | ||||
|         expect(wrapper.vm.scopedLabel(mockRegularLabel)).toBe(false); | ||||
|       }); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe('template', () => { | ||||
|     it('renders class `has-labels` on component container element when `selectedLabels` is not empty', () => { | ||||
|       createComponent(); | ||||
| 
 | ||||
|       expect(wrapper.attributes('class')).toContain('has-labels'); | ||||
|     }); | ||||
| 
 | ||||
|     it('renders element containing `None` when `selectedLabels` is empty', () => { | ||||
|       createComponent( | ||||
|         { | ||||
|           selectedLabels: [], | ||||
|  | @ -73,16 +42,56 @@ describe('DropdownValue', () => { | |||
|           default: 'None', | ||||
|         }, | ||||
|       ); | ||||
|       const noneEl = wrapper.find('span.text-secondary'); | ||||
| 
 | ||||
|       expect(noneEl.exists()).toBe(true); | ||||
|       expect(noneEl.text()).toBe('None'); | ||||
|     }); | ||||
| 
 | ||||
|     it('renders labels when `selectedLabels` is not empty', () => { | ||||
|       createComponent(); | ||||
|     it('does not apply `has-labels` class to the wrapping container', () => { | ||||
|       expect(findWrapper().classes()).not.toContain('has-labels'); | ||||
|     }); | ||||
| 
 | ||||
|       expect(wrapper.findAll(GlLabel).length).toBe(2); | ||||
|     it('renders an empty placeholder', () => { | ||||
|       expect(findEmptyPlaceholder().exists()).toBe(true); | ||||
|       expect(findEmptyPlaceholder().text()).toBe('None'); | ||||
|     }); | ||||
| 
 | ||||
|     it('does not render any labels', () => { | ||||
|       expect(findAllLabels().length).toBe(0); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe('when there are labels', () => { | ||||
|     beforeEach(() => { | ||||
|       createComponent(); | ||||
|     }); | ||||
| 
 | ||||
|     it('applies `has-labels` class to the wrapping container', () => { | ||||
|       expect(findWrapper().classes()).toContain('has-labels'); | ||||
|     }); | ||||
| 
 | ||||
|     it('does not render an empty placeholder', () => { | ||||
|       expect(findEmptyPlaceholder().exists()).toBe(false); | ||||
|     }); | ||||
| 
 | ||||
|     it('renders a list of two labels', () => { | ||||
|       expect(findAllLabels().length).toBe(2); | ||||
|     }); | ||||
| 
 | ||||
|     it('passes correct props to the regular label', () => { | ||||
|       expect(findRegularLabel().props('target')).toBe( | ||||
|         '/gitlab-org/my-project/issues?label_name[]=Foo%20Label', | ||||
|       ); | ||||
|       expect(findRegularLabel().props('scoped')).toBe(false); | ||||
|     }); | ||||
| 
 | ||||
|     it('passes correct props to the scoped label', () => { | ||||
|       expect(findScopedLabel().props('target')).toBe( | ||||
|         '/gitlab-org/my-project/issues?label_name[]=Foo%3A%3ABar', | ||||
|       ); | ||||
|       expect(findScopedLabel().props('scoped')).toBe(true); | ||||
|     }); | ||||
| 
 | ||||
|     it('emits `onLabelRemove` event with the correct ID', () => { | ||||
|       findRegularLabel().vm.$emit('close'); | ||||
|       expect(wrapper.emitted('onLabelRemove')).toEqual([[mockRegularLabel.id]]); | ||||
|     }); | ||||
|   }); | ||||
| }); | ||||
|  |  | |||
|  | @ -34,6 +34,10 @@ describe('LabelsSelectRoot', () => { | |||
|       stubs: { | ||||
|         'dropdown-contents': DropdownContents, | ||||
|       }, | ||||
|       provide: { | ||||
|         iid: '1', | ||||
|         projectPath: 'test', | ||||
|       }, | ||||
|     }); | ||||
|   }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import { GlButton } from '@gitlab/ui'; | ||||
| import { shallowMount, mount } from '@vue/test-utils'; | ||||
| import TodoButton from '~/vue_shared/components/todo_button.vue'; | ||||
| import TodoButton from '~/vue_shared/components/sidebar/todo_button.vue'; | ||||
| 
 | ||||
| describe('Todo Button', () => { | ||||
|   let wrapper; | ||||
		Loading…
	
		Reference in New Issue