diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-06 09:08:13 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-06 09:08:13 +0000 |
commit | 8e94dad32b10edebf79285c083176c2b7005ef64 (patch) | |
tree | 3bb66395f2962063ca0d20f98b35ac852d801c7e | |
parent | ab128cc125f9db0c3a1bd48845f90c3d61ef42c9 (diff) | |
download | gitlab-ce-8e94dad32b10edebf79285c083176c2b7005ef64.tar.gz |
Add latest changes from gitlab-org/gitlab@master
22 files changed, 257 insertions, 137 deletions
diff --git a/app/assets/javascripts/confirm_modal.js b/app/assets/javascripts/confirm_modal.js index 1c9346e35e0..ff29d5fa355 100644 --- a/app/assets/javascripts/confirm_modal.js +++ b/app/assets/javascripts/confirm_modal.js @@ -1,26 +1,45 @@ import Vue from 'vue'; import ConfirmModal from '~/vue_shared/components/confirm_modal.vue'; -const mountConfirmModal = button => { - const props = { - path: button.dataset.path, - method: button.dataset.method, - modalAttributes: JSON.parse(button.dataset.modalAttributes), - }; - +const mountConfirmModal = () => { return new Vue({ + data() { + return { + path: '', + method: '', + modalAttributes: null, + showModal: false, + }; + }, + mounted() { + document.querySelectorAll('.js-confirm-modal-button').forEach(button => { + button.addEventListener('click', e => { + e.preventDefault(); + + this.path = button.dataset.path; + this.method = button.dataset.method; + this.modalAttributes = JSON.parse(button.dataset.modalAttributes); + this.showModal = true; + }); + }); + }, + methods: { + dismiss() { + this.showModal = false; + }, + }, render(h) { - return h(ConfirmModal, { props }); + return h(ConfirmModal, { + props: { + path: this.path, + method: this.method, + modalAttributes: this.modalAttributes, + showModal: this.showModal, + }, + on: { dismiss: this.dismiss }, + }); }, }).$mount(); }; -export default () => { - document.getElementsByClassName('js-confirm-modal-button').forEach(button => { - button.addEventListener('click', e => { - e.preventDefault(); - - mountConfirmModal(button); - }); - }); -}; +export default () => mountConfirmModal(); diff --git a/app/assets/javascripts/filtered_search/dropdown_utils.js b/app/assets/javascripts/filtered_search/dropdown_utils.js index 274c08e6955..43de86b09ee 100644 --- a/app/assets/javascripts/filtered_search/dropdown_utils.js +++ b/app/assets/javascripts/filtered_search/dropdown_utils.js @@ -1,4 +1,4 @@ -import _ from 'underscore'; +import { last } from 'lodash'; import FilteredSearchContainer from './container'; import FilteredSearchTokenizer from './filtered_search_tokenizer'; import FilteredSearchDropdownManager from './filtered_search_dropdown_manager'; @@ -70,11 +70,11 @@ export default class DropdownUtils { if (!allowMultiple && itemInExistingTokens) { updatedItem.droplab_hidden = true; - } else if (!isSearchItem && (!lastKey || _.last(searchInput.split('')) === ' ')) { + } else if (!isSearchItem && (!lastKey || last(searchInput.split('')) === ' ')) { updatedItem.droplab_hidden = false; } else if (lastKey) { const split = lastKey.split(':'); - const tokenName = _.last(split[0].split(' ')); + const tokenName = last(split[0].split(' ')); const match = isSearchItem ? allowedKeys.some(key => key.startsWith(tokenName.toLowerCase())) @@ -129,7 +129,7 @@ export default class DropdownUtils { const values = []; if (untilInput) { - const inputIndex = _.findIndex(tokens, t => t.classList.contains('input-token')); + const inputIndex = tokens.findIndex(t => t.classList.contains('input-token')); // Add one to include input-token to the tokens array tokens.splice(inputIndex + 1); } diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js index 03f65612b60..d051b60814e 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js +++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js @@ -1,5 +1,5 @@ +import { last } from 'lodash'; import AvailableDropdownMappings from 'ee_else_ce/filtered_search/available_dropdown_mappings'; -import _ from 'underscore'; import DropLab from '~/droplab/drop_lab'; import FilteredSearchContainer from './container'; import FilteredSearchTokenKeys from './filtered_search_token_keys'; @@ -184,8 +184,8 @@ export default class FilteredSearchDropdownManager { // Eg. token = 'label:' const split = lastToken.split(':'); - const dropdownName = _.last(split[0].split(' ')); - const possibleOperatorToken = _.last(split[1]); + const dropdownName = last(split[0].split(' ')); + const possibleOperatorToken = last(split[1]); const hasOperator = FilteredSearchVisualTokens.permissibleOperatorValues.includes( possibleOperatorToken && possibleOperatorToken.trim(), diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js index 88737396113..7ea7313f648 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_manager.js +++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js @@ -1,4 +1,4 @@ -import _ from 'underscore'; +import { last } from 'lodash'; import recentSearchesStorageKeys from 'ee_else_ce/filtered_search/recent_searches_storage_keys'; import { getParameterByName, getUrlParamsArray } from '~/lib/utils/common_utils'; import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys'; @@ -456,7 +456,7 @@ export default class FilteredSearchManager { if (fragments.length > 1) { const inputValues = fragments[0].split(' '); - const tokenKey = _.last(inputValues); + const tokenKey = last(inputValues); if (inputValues.length > 1) { inputValues.pop(); diff --git a/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js b/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js index 8722fc64b62..9bea7aa7b04 100644 --- a/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js +++ b/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js @@ -1,4 +1,4 @@ -import { flatten } from 'underscore'; +import { flattenDeep } from 'lodash'; import FilteredSearchTokenKeys from './filtered_search_token_keys'; import { __ } from '~/locale'; @@ -73,7 +73,7 @@ export const alternativeTokenKeys = [ }, ]; -export const conditions = flatten( +export const conditions = flattenDeep( [ { url: 'assignee_id=None', diff --git a/app/assets/javascripts/filtered_search/stores/recent_searches_store.js b/app/assets/javascripts/filtered_search/stores/recent_searches_store.js index 76d40bfdaf8..b3eb0475d6f 100644 --- a/app/assets/javascripts/filtered_search/stores/recent_searches_store.js +++ b/app/assets/javascripts/filtered_search/stores/recent_searches_store.js @@ -1,4 +1,4 @@ -import _ from 'underscore'; +import { uniq } from 'lodash'; class RecentSearchesStore { constructor(initialState = {}, allowedKeys) { @@ -20,7 +20,7 @@ class RecentSearchesStore { setRecentSearches(searches = []) { const trimmedSearches = searches.map(search => search.trim()); - this.state.recentSearches = _.uniq(trimmedSearches).slice(0, 5); + this.state.recentSearches = uniq(trimmedSearches).slice(0, 5); return this.state.recentSearches; } } diff --git a/app/assets/javascripts/filtered_search/visual_token_value.js b/app/assets/javascripts/filtered_search/visual_token_value.js index b7ac655b619..b8f4cd8a1e1 100644 --- a/app/assets/javascripts/filtered_search/visual_token_value.js +++ b/app/assets/javascripts/filtered_search/visual_token_value.js @@ -1,4 +1,4 @@ -import _ from 'underscore'; +import { escape as esc } from 'lodash'; import { USER_TOKEN_TYPES } from 'ee_else_ce/filtered_search/constants'; import FilteredSearchContainer from '~/filtered_search/container'; import FilteredSearchVisualTokens from '~/filtered_search/filtered_search_visual_tokens'; @@ -48,7 +48,7 @@ export default class VisualTokenValue { tokenValueContainer.dataset.originalValue = tokenValue; tokenValueElement.innerHTML = ` <img class="avatar s20" src="${user.avatar_url}" alt=""> - ${_.escape(user.name)} + ${esc(user.name)} `; /* eslint-enable no-param-reassign */ }) diff --git a/app/assets/javascripts/vue_shared/components/confirm_modal.vue b/app/assets/javascripts/vue_shared/components/confirm_modal.vue index 21722f62133..c77827205d6 100644 --- a/app/assets/javascripts/vue_shared/components/confirm_modal.vue +++ b/app/assets/javascripts/vue_shared/components/confirm_modal.vue @@ -9,34 +9,43 @@ export default { props: { modalAttributes: { type: Object, - required: true, + required: false, + default: () => { + return {}; + }, }, path: { type: String, - required: true, + required: false, + default: '', }, method: { type: String, - required: true, + required: false, + default: '', + }, + showModal: { + type: Boolean, + required: false, + default: false, }, }, - data() { - return { - isDismissed: false, - }; - }, - mounted() { - this.openModal(); + watch: { + showModal(val) { + if (val) { + // Wait for v-if to render + this.$nextTick(() => { + this.openModal(); + }); + } + }, }, methods: { openModal() { this.$refs.modal.show(); }, submitModal() { - this.$refs.form.requestSubmit(); - }, - dismiss() { - this.isDismissed = true; + this.$refs.form.submit(); }, }, csrf, @@ -45,11 +54,11 @@ export default { <template> <gl-modal - v-if="!isDismissed" + v-if="showModal" ref="modal" v-bind="modalAttributes" @primary="submitModal" - @canceled="dismiss" + @canceled="$emit('dismiss')" > <form ref="form" :action="path" method="post"> <!-- Rails workaround for <form method="delete" /> diff --git a/app/models/clusters/applications/cert_manager.rb b/app/models/clusters/applications/cert_manager.rb index 7ba04d1a2de..1efa44c39c5 100644 --- a/app/models/clusters/applications/cert_manager.rb +++ b/app/models/clusters/applications/cert_manager.rb @@ -3,8 +3,8 @@ module Clusters module Applications class CertManager < ApplicationRecord - VERSION = 'v0.9.1' - CRD_VERSION = '0.9' + VERSION = 'v0.10.1' + CRD_VERSION = '0.10' self.table_name = 'clusters_applications_cert_managers' diff --git a/changelogs/unreleased/196883-repository-link-grpc-graceful-failure.yml b/changelogs/unreleased/196883-repository-link-grpc-graceful-failure.yml new file mode 100644 index 00000000000..3cc335c7ee9 --- /dev/null +++ b/changelogs/unreleased/196883-repository-link-grpc-graceful-failure.yml @@ -0,0 +1,5 @@ +--- +title: Ensure RepositoryLinkFilter handles Gitaly failures gracefully +merge_request: 26531 +author: +type: performance diff --git a/changelogs/unreleased/208678-packages-project-and-group-api-will-return-processing-nuget-packag.yml b/changelogs/unreleased/208678-packages-project-and-group-api-will-return-processing-nuget-packag.yml new file mode 100644 index 00000000000..0596f0e4b85 --- /dev/null +++ b/changelogs/unreleased/208678-packages-project-and-group-api-will-return-processing-nuget-packag.yml @@ -0,0 +1,5 @@ +--- +title: Fixed bug where processing NuGet packages are returned from the Packages API +merge_request: 26270 +author: +type: fixed diff --git a/changelogs/unreleased/ee-insert-all-for-load-balancing.yml b/changelogs/unreleased/ee-insert-all-for-load-balancing.yml new file mode 100644 index 00000000000..135f97cb488 --- /dev/null +++ b/changelogs/unreleased/ee-insert-all-for-load-balancing.yml @@ -0,0 +1,5 @@ +--- +title: Support Rails 6 `insert_all!` +merge_request: 26595 +author: +type: fixed diff --git a/changelogs/unreleased/update-cert-manager-to-0-10-1.yml b/changelogs/unreleased/update-cert-manager-to-0-10-1.yml new file mode 100644 index 00000000000..886ab67dfc4 --- /dev/null +++ b/changelogs/unreleased/update-cert-manager-to-0-10-1.yml @@ -0,0 +1,5 @@ +--- +title: Use cert-manager 0.10 instead of 0.9 for new chart installations +merge_request: 26345 +author: +type: changed diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md index e14e8ceb8c0..e51cda3c300 100644 --- a/doc/user/application_security/container_scanning/index.md +++ b/doc/user/application_security/container_scanning/index.md @@ -107,24 +107,20 @@ artifact available. Behind the scenes, the [GitLab Klar analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/klar/) is used and runs the scans. -### Example - -The following is a sample `.gitlab-ci.yml` that will build your Docker Image, push it to the container registry and run Container Scanning. +The following is a sample `.gitlab-ci.yml` that will build your Docker image, +push it to the Container Registry, and run Container Scanning: ```yaml variables: DOCKER_DRIVER: overlay2 services: - - docker:stable-dind + - docker:19.03.5-dind stages: - build - test -include: - - template: Container-Scanning.gitlab-ci.yml - build: image: docker:stable stage: build @@ -135,40 +131,37 @@ build: - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY - docker build -t $IMAGE . - docker push $IMAGE + +include: + - template: Container-Scanning.gitlab-ci.yml ``` -### Vulnerability Whitelisting +### Customizing the Container Scanning settings -If you want to whitelist specific vulnerabilities, you'll need to: +You can change container scanning settings by using the [`variables`](../../../ci/yaml/README.md#variables) +parameter in your `.gitlab-ci.yml` to change [environment variables](#available-variables). - 1. Set [`GIT_STRATEGY: fetch`](../../../ci/yaml/README.md#git-strategy) in your `.gitlab-ci.yml` file by following the instructions described in the - [overriding the Container Scanning template](#overriding-the-container-scanning-template) section of this document. - 1. Define the whitelisted vulnerabilities in a YAML file named `clair-whitelist.yml` which must use the format described - in the [following whitelist example file](https://github.com/arminc/clair-scanner/blob/v12/example-whitelist.yaml). - 1. Add the `clair-whitelist.yml` file to the Git repository of your project - -### Overriding the Container Scanning template - -If you want to override the job definition (for example, change properties like -`variables`), you need to declare a `container_scanning` job after the -template inclusion and specify any additional keys under it. For example: +In the following example, we [include](../../../ci/yaml/README.md#include) the template and also +set the `CLAIR_OUTPUT` variable to `High`: ```yaml include: - - template: Container-Scanning.gitlab-ci.yml + template: Container-Scanning.gitlab-ci.yml -container_scanning: - variables: - GIT_STRATEGY: fetch +variables: + CLAIR_OUTPUT: High ``` +The `CLAIR_OUTPUT` variable defined in the main `gitlab-ci.yml` will overwrite what's +defined in `Container-Scanning.gitlab-ci.yml`, changing the Container Scanning behavior. + [//]: # "NOTE: The container scanning tool references the following heading in the code, so if you" [//]: # " make a change to this heading, make sure to update the documentation URLs used in the" [//]: # " container scanning tool (https://gitlab.com/gitlab-org/security-products/analyzers/klar)" -### Available variables +#### Available variables -Container Scanning can be [configured](#overriding-the-container-scanning-template) +Container Scanning can be [configured](#customizing-the-container-scanning-settings) using environment variables. | Environment Variable | Description | Default | @@ -187,36 +180,32 @@ using environment variables. | `CLAIR_DB_IMAGE_TAG` | (**DEPRECATED - use `CLAIR_DB_IMAGE` instead**) The Docker image tag for the [Postgres server hosting the vulnerabilities definitions](https://hub.docker.com/r/arminc/clair-db). It can be useful to override this value with a specific version, for example, to provide a consistent set of vulnerabilities for integration testing purposes. | `latest` | | `DOCKERFILE_PATH` | The path to the `Dockerfile` to be used for generating remediations. By default, the scanner will look for a file named `Dockerfile` in the root directory of the project, so this variable should only be configured if your `Dockerfile` is in a non-standard location, such as a subdirectory. See [Solutions for vulnerabilities](#solutions-for-vulnerabilities-auto-remediation) for more details. | `Dockerfile` | -## Security Dashboard - -The Security Dashboard is a good place to get an overview of all the security -vulnerabilities in your groups, projects and pipelines. Read more about the -[Security Dashboard](../security_dashboard/index.md). - -## Interacting with the vulnerabilities - -Once a vulnerability is found, you can interact with it. Read more on how to -[interact with the vulnerabilities](../index.md#interacting-with-the-vulnerabilities). +### Overriding the Container Scanning template -## Solutions for vulnerabilities (auto-remediation) +If you want to override the job definition (for example, change properties like +`variables`), you need to declare a `container_scanning` job after the +template inclusion and specify any additional keys under it. For example: -Some vulnerabilities can be fixed by applying the solution that GitLab -automatically generates. +```yaml +include: + template: Container-Scanning.gitlab-ci.yml -To enable remediation support, the scanning tool _must_ have access to the `Dockerfile` specified by -the `DOCKERFILE_PATH` environment variable. To ensure that the scanning tool has access to this -file, it's necessary to set [`GIT_STRATEGY: fetch`](../../../ci/yaml/README.md#git-strategy) in -your `.gitlab-ci.yml` file by following the instructions described in this document's -[overriding the Container Scanning template](#overriding-the-container-scanning-template) section. +container_scanning: + variables: + GIT_STRATEGY: fetch +``` -Read more about the [solutions for vulnerabilities](../index.md#solutions-for-vulnerabilities-auto-remediation). +### Vulnerability whitelisting -## Vulnerabilities database update +If you want to whitelist specific vulnerabilities, you'll need to: -For more information about the vulnerabilities database update, check the -[maintenance table](../index.md#maintenance-and-update-of-the-vulnerabilities-database). +1. Set `GIT_STRATEGY: fetch` in your `.gitlab-ci.yml` file by following the instructions described in the + [overriding the Container Scanning template](#overriding-the-container-scanning-template) section of this document. +1. Define the whitelisted vulnerabilities in a YAML file named `clair-whitelist.yml` which must use the format described + in the [whitelist example file](https://github.com/arminc/clair-scanner/blob/v12/example-whitelist.yaml). +1. Add the `clair-whitelist.yml` file to the Git repository of your project. -## Running Container Scanning in an offline air-gapped installation +### Running Container Scanning in an offline, air-gapped installation Container Scanning can be executed on an offline air-gapped GitLab Ultimate installation using the following process: @@ -245,7 +234,7 @@ It may be worthwhile to set up a [scheduled pipeline](../../../ci/pipelines/sche image: docker:stable services: - - docker:stable-dind + - docker:19.03.5-dind stages: - build @@ -396,6 +385,33 @@ the report JSON unless stated otherwise. Presence of optional fields depends on | `remediations[].summary` | Overview of how the vulnerabilities have been fixed. | | `remediations[].diff` | base64-encoded remediation code diff, compatible with [`git apply`](https://git-scm.com/docs/git-format-patch#_discussion). | +## Security Dashboard + +The [Security Dashboard](../security_dashboard/index.md) shows you an overview of all +the security vulnerabilities in your groups, projects and pipelines. + +## Vulnerabilities database update + +For more information about the vulnerabilities database update, check the +[maintenance table](../index.md#maintenance-and-update-of-the-vulnerabilities-database). + +## Interacting with the vulnerabilities + +Once a vulnerability is found, you can [interact with it](../index.md#interacting-with-the-vulnerabilities). + +## Solutions for vulnerabilities (auto-remediation) + +Some vulnerabilities can be fixed by applying the solution that GitLab +automatically generates. + +To enable remediation support, the scanning tool _must_ have access to the `Dockerfile` specified by +the `DOCKERFILE_PATH` environment variable. To ensure that the scanning tool has access to this +file, it's necessary to set [`GIT_STRATEGY: fetch`](../../../ci/yaml/README.md#git-strategy) in +your `.gitlab-ci.yml` file by following the instructions described in this document's +[overriding the Container Scanning template](#overriding-the-container-scanning-template) section. + +Read more about the [solutions for vulnerabilities](../index.md#solutions-for-vulnerabilities-auto-remediation). + ## Troubleshooting ### docker: Error response from daemon: failed to copy xattrs diff --git a/lib/api/project_container_repositories.rb b/lib/api/project_container_repositories.rb index 0fd887f4458..555fd98b451 100644 --- a/lib/api/project_container_repositories.rb +++ b/lib/api/project_container_repositories.rb @@ -70,14 +70,9 @@ module API params do requires :repository_id, type: Integer, desc: 'The ID of the repository' optional :name_regex_delete, type: String, desc: 'The tag name regexp to delete, specify .* to delete all' - # require either name_regex (deprecated) or name_regex_delete, it is ok to have both - given name_regex_delete: ->(val) { val.nil? } do - requires :name_regex, type: String, desc: 'The tag name regexp to delete, specify .* to delete all' - end optional :name_regex, type: String, desc: 'The tag name regexp to delete, specify .* to delete all' - given name_regex: ->(val) { val.nil? } do - requires :name_regex_delete, type: String, desc: 'The tag name regexp to delete, specify .* to delete all' - end + # require either name_regex (deprecated) or name_regex_delete, it is ok to have both + at_least_one_of :name_regex, :name_regex_delete optional :name_regex_keep, type: String, desc: 'The tag name regexp to retain' optional :keep_n, type: Integer, desc: 'Keep n of latest tags with matching name' optional :older_than, type: String, desc: 'Delete older than: 1h, 1d, 1month' diff --git a/lib/banzai/filter/repository_link_filter.rb b/lib/banzai/filter/repository_link_filter.rb index d448238c6e4..e15201b05cb 100644 --- a/lib/banzai/filter/repository_link_filter.rb +++ b/lib/banzai/filter/repository_link_filter.rb @@ -80,6 +80,13 @@ module Banzai end Gitlab::GitalyClient::BlobService.new(repository).get_blob_types(revision_paths, 1) + rescue GRPC::Unavailable, GRPC::DeadlineExceeded => e + # Handle Gitaly connection issues gracefully + Gitlab::ErrorTracking.track_exception(e, project_id: project.id) + # Return all links as blob types + paths.collect do |path| + [path, :blob] + end end def get_uri(html_attr) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 057f6a41980..cb9cff0b988 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -9250,6 +9250,12 @@ msgstr "" msgid "Geo|Remove" msgstr "" +msgid "Geo|Remove entry" +msgstr "" + +msgid "Geo|Remove tracking database entry" +msgstr "" + msgid "Geo|Repository sync capacity" msgstr "" @@ -9301,13 +9307,13 @@ msgstr "" msgid "Geo|This is a primary node" msgstr "" -msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed." +msgid "Geo|Tracking database entry will be removed. Are you sure?" msgstr "" -msgid "Geo|Tracking entry for upload (%{type}/%{id}) was successfully removed." +msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed." msgstr "" -msgid "Geo|Tracking entry will be removed. Are you sure?" +msgid "Geo|Tracking entry for upload (%{type}/%{id}) was successfully removed." msgstr "" msgid "Geo|URL" diff --git a/spec/frontend/helpers/dom_shims/form_element.js b/spec/frontend/helpers/dom_shims/form_element.js new file mode 100644 index 00000000000..46ef0374848 --- /dev/null +++ b/spec/frontend/helpers/dom_shims/form_element.js @@ -0,0 +1 @@ +HTMLFormElement.prototype.submit = jest.fn(); diff --git a/spec/frontend/helpers/dom_shims/index.js b/spec/frontend/helpers/dom_shims/index.js index 855b707a4cf..bcd5da0ce48 100644 --- a/spec/frontend/helpers/dom_shims/index.js +++ b/spec/frontend/helpers/dom_shims/index.js @@ -1,4 +1,5 @@ import './element_scroll_into_view'; +import './form_element'; import './get_client_rects'; import './inner_text'; import './window_scroll_to'; diff --git a/spec/frontend/vue_shared/components/confirm_modal_spec.js b/spec/frontend/vue_shared/components/confirm_modal_spec.js index 722380d3383..d3dea73e4a6 100644 --- a/spec/frontend/vue_shared/components/confirm_modal_spec.js +++ b/spec/frontend/vue_shared/components/confirm_modal_spec.js @@ -3,6 +3,8 @@ import { GlModal } from '@gitlab/ui'; import { TEST_HOST } from 'helpers/test_constants'; import ConfirmModal from '~/vue_shared/components/confirm_modal.vue'; +jest.mock('~/lib/utils/csrf', () => ({ token: 'test-csrf-token' })); + describe('vue_shared/components/confirm_modal', () => { const testModalProps = { path: `${TEST_HOST}/1`, @@ -39,45 +41,61 @@ describe('vue_shared/components/confirm_modal', () => { }); const findModal = () => wrapper.find(GlModal); + const findForm = () => wrapper.find('form'); + const findFormData = () => + findForm() + .findAll('input') + .wrappers.map(x => ({ name: x.attributes('name'), value: x.attributes('value') })); describe('template', () => { - beforeEach(() => { - createComponent(); - }); + describe('when showModal is false', () => { + beforeEach(() => { + createComponent(); + }); - it('calls openModal on mount', () => { - expect(actionSpies.openModal).toHaveBeenCalled(); + it('does not render GlModal', () => { + expect(findModal().exists()).toBeFalsy(); + }); }); - it('renders GlModal', () => { - expect(findModal().exists()).toBeTruthy(); + describe('when showModal is true', () => { + beforeEach(() => { + createComponent({ showModal: true }); + }); + + it('renders GlModal', () => { + expect(findModal().exists()).toBeTruthy(); + expect(findModal().attributes()).toEqual( + expect.objectContaining({ + modalid: testModalProps.modalAttributes.modalId, + oktitle: testModalProps.modalAttributes.okTitle, + okvariant: testModalProps.modalAttributes.okVariant, + }), + ); + }); }); }); describe('methods', () => { beforeEach(() => { - createComponent(); + createComponent({ showModal: true }); }); - describe('submitModal', () => { - beforeEach(() => { - wrapper.vm.$refs.form.requestSubmit = jest.fn(); - }); - - it('calls requestSubmit', () => { - wrapper.vm.submitModal(); - expect(wrapper.vm.$refs.form.requestSubmit).toHaveBeenCalled(); - }); + it('does not submit form', () => { + expect(findForm().element.submit).not.toHaveBeenCalled(); }); - describe('dismiss', () => { - it('removes gl-modal', () => { - expect(findModal().exists()).toBeTruthy(); - wrapper.vm.dismiss(); + describe('when modal submitted', () => { + beforeEach(() => { + findModal().vm.$emit('primary'); + }); - return wrapper.vm.$nextTick(() => { - expect(findModal().exists()).toBeFalsy(); - }); + it('submits form', () => { + expect(findFormData()).toEqual([ + { name: '_method', value: testModalProps.method }, + { name: 'authenticity_token', value: 'test-csrf-token' }, + ]); + expect(findForm().element.submit).toHaveBeenCalled(); }); }); }); diff --git a/spec/lib/banzai/filter/repository_link_filter_spec.rb b/spec/lib/banzai/filter/repository_link_filter_spec.rb index cf73c77ecb8..f093a5b0a79 100644 --- a/spec/lib/banzai/filter/repository_link_filter_spec.rb +++ b/spec/lib/banzai/filter/repository_link_filter_spec.rb @@ -149,6 +149,34 @@ describe Banzai::Filter::RepositoryLinkFilter do end shared_examples :valid_repository do + it 'handles Gitaly unavailable exceptions gracefully' do + allow_next_instance_of(Gitlab::GitalyClient::BlobService) do |blob_service| + allow(blob_service).to receive(:get_blob_types).and_raise(GRPC::Unavailable) + end + + expect(Gitlab::ErrorTracking).to receive(:track_exception).with( + an_instance_of(GRPC::Unavailable), project_id: project.id + ) + doc = "" + expect { doc = filter(link('doc/api/README.md')) }.not_to raise_error + expect(doc.at_css('a')['href']) + .to eq "/#{project_path}/-/blob/#{ref}/doc/api/README.md" + end + + it 'handles Gitaly timeout exceptions gracefully' do + allow_next_instance_of(Gitlab::GitalyClient::BlobService) do |blob_service| + allow(blob_service).to receive(:get_blob_types).and_raise(GRPC::DeadlineExceeded) + end + + expect(Gitlab::ErrorTracking).to receive(:track_exception).with( + an_instance_of(GRPC::DeadlineExceeded), project_id: project.id + ) + doc = "" + expect { doc = filter(link('doc/api/README.md')) }.not_to raise_error + expect(doc.at_css('a')['href']) + .to eq "/#{project_path}/-/blob/#{ref}/doc/api/README.md" + end + it 'rebuilds absolute URL for a file in the repo' do doc = filter(link('/doc/api/README.md')) expect(doc.at_css('a')['href']) diff --git a/spec/models/clusters/applications/cert_manager_spec.rb b/spec/models/clusters/applications/cert_manager_spec.rb index 31209a70018..d7fd0d06b05 100644 --- a/spec/models/clusters/applications/cert_manager_spec.rb +++ b/spec/models/clusters/applications/cert_manager_spec.rb @@ -46,11 +46,11 @@ describe Clusters::Applications::CertManager do expect(subject.name).to eq('certmanager') expect(subject.chart).to eq('certmanager/cert-manager') expect(subject.repository).to eq('https://charts.jetstack.io') - expect(subject.version).to eq('v0.9.1') + expect(subject.version).to eq('v0.10.1') expect(subject).to be_rbac expect(subject.files).to eq(cert_manager.files.merge(cluster_issuer_file)) expect(subject.preinstall).to eq([ - 'kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.9/deploy/manifests/00-crds.yaml', + 'kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.10/deploy/manifests/00-crds.yaml', 'kubectl label --overwrite namespace gitlab-managed-apps certmanager.k8s.io/disable-validation=true' ]) expect(subject.postinstall).to eq([ @@ -82,7 +82,7 @@ describe Clusters::Applications::CertManager do let(:cert_manager) { create(:clusters_applications_cert_manager, :errored, version: '0.0.1') } it 'is initialized with the locked version' do - expect(subject.version).to eq('v0.9.1') + expect(subject.version).to eq('v0.10.1') end end end |