diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-07-09 09:08:14 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-07-09 09:08:14 +0300 |
commit | 97576e3dfdc15b26c0a7832608397edd69167351 (patch) | |
tree | 90d29c6f48f6df6f9b23d6435baa8a903331a17b | |
parent | a27d3c27d8a81a2d2b7300d6099e94a2bfb30123 (diff) |
Add latest changes from gitlab-org/gitlab@master
12 files changed, 136 insertions, 16 deletions
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml index faafc8ef0e1..0b6675ab84f 100644 --- a/.gitlab/ci/review.gitlab-ci.yml +++ b/.gitlab/ci/review.gitlab-ci.yml @@ -25,7 +25,7 @@ review-build-cng: extends: - .default-retry - .review:rules:review-build-cng - image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7-alpine + image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7 stage: review-prepare before_script: - source ./scripts/utils.sh diff --git a/.gitlab/ci/setup.gitlab-ci.yml b/.gitlab/ci/setup.gitlab-ci.yml index 27b68115edc..7b1c25d3af9 100644 --- a/.gitlab/ci/setup.gitlab-ci.yml +++ b/.gitlab/ci/setup.gitlab-ci.yml @@ -52,7 +52,7 @@ no_ee_check: verify-tests-yml: extends: - .setup:rules:verify-tests-yml - image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7-alpine + image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7 stage: test needs: [] script: diff --git a/app/assets/javascripts/content_editor/components/wrappers/image.vue b/app/assets/javascripts/content_editor/components/wrappers/image.vue new file mode 100644 index 00000000000..3762324a431 --- /dev/null +++ b/app/assets/javascripts/content_editor/components/wrappers/image.vue @@ -0,0 +1,31 @@ +<script> +import { GlLoadingIcon } from '@gitlab/ui'; +import { NodeViewWrapper } from '@tiptap/vue-2'; + +export default { + name: 'ImageWrapper', + components: { + NodeViewWrapper, + GlLoadingIcon, + }, + props: { + node: { + type: Object, + required: true, + }, + }, +}; +</script> +<template> + <node-view-wrapper class="gl-display-inline-block"> + <span class="gl-relative"> + <img + data-testid="image" + class="gl-max-w-full gl-h-auto" + :class="{ 'gl-opacity-5': node.attrs.uploading }" + :src="node.attrs.src" + /> + <gl-loading-icon v-if="node.attrs.uploading" class="gl-absolute gl-left-50p gl-top-half" /> + </span> + </node-view-wrapper> +</template> diff --git a/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue b/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue index 372368707af..dc0f2b54a7b 100644 --- a/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue +++ b/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue @@ -4,7 +4,7 @@ import Vue from 'vue'; import createFlash from '~/flash'; import { __, sprintf } from '~/locale'; import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue'; -import { confidentialityQueries } from '~/sidebar/constants'; +import { confidentialityQueries, Tracking } from '~/sidebar/constants'; import SidebarConfidentialityContent from './sidebar_confidentiality_content.vue'; import SidebarConfidentialityForm from './sidebar_confidentiality_form.vue'; @@ -18,8 +18,8 @@ const hideDropdownEvent = new CustomEvent('hiddenGlDropdown', { export default { tracking: { - event: 'click_edit_button', - label: 'right_sidebar', + event: Tracking.editEvent, + label: Tracking.rightSidebarLabel, property: 'confidentiality', }, components: { diff --git a/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue b/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue index 14815bf6d06..1ff24dec884 100644 --- a/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue +++ b/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue @@ -5,7 +5,13 @@ import { IssuableType } from '~/issue_show/constants'; import { dateInWords, formatDate, parsePikadayDate } from '~/lib/utils/datetime_utility'; import { __, sprintf } from '~/locale'; import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue'; -import { dateFields, dateTypes, dueDateQueries, startDateQueries } from '~/sidebar/constants'; +import { + dateFields, + dateTypes, + dueDateQueries, + startDateQueries, + Tracking, +} from '~/sidebar/constants'; import SidebarFormattedDate from './sidebar_formatted_date.vue'; import SidebarInheritDate from './sidebar_inherit_date.vue'; @@ -15,8 +21,8 @@ const hideDropdownEvent = new CustomEvent('hiddenGlDropdown', { export default { tracking: { - event: 'click_edit_button', - label: 'right_sidebar', + event: Tracking.editEvent, + label: Tracking.rightSidebarLabel, }, directives: { GlTooltip: GlTooltipDirective, diff --git a/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue b/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue index 141a5f34864..a7ff9c0efc8 100644 --- a/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue +++ b/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue @@ -16,12 +16,13 @@ import { IssuableType } from '~/issue_show/constants'; import { __, s__, sprintf } from '~/locale'; import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue'; import { + Tracking, IssuableAttributeState, IssuableAttributeType, issuableAttributesQueries, noAttributeId, defaultEpicSort, -} from '../constants'; +} from '~/sidebar/constants'; export default { noAttributeId, @@ -148,8 +149,8 @@ export default { currentAttribute: null, attributesList: [], tracking: { - label: 'right_sidebar', - event: 'click_edit_button', + event: Tracking.editEvent, + label: Tracking.rightSidebarLabel, property: this.issuableAttribute, }, }; diff --git a/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue b/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue index 436f4f2b66d..bc7e377a966 100644 --- a/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue +++ b/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue @@ -5,15 +5,15 @@ import { IssuableType } from '~/issue_show/constants'; import { isLoggedIn } from '~/lib/utils/common_utils'; import { __, sprintf } from '~/locale'; import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue'; -import { subscribedQueries } from '~/sidebar/constants'; +import { subscribedQueries, Tracking } from '~/sidebar/constants'; const ICON_ON = 'notifications'; const ICON_OFF = 'notifications-off'; export default { tracking: { - event: 'click_edit_button', - label: 'right_sidebar', + event: Tracking.editEvent, + label: Tracking.rightSidebarLabel, property: 'subscriptions', }, directives: { diff --git a/app/assets/javascripts/sidebar/constants.js b/app/assets/javascripts/sidebar/constants.js index 91afa75bba9..74f389f86dc 100644 --- a/app/assets/javascripts/sidebar/constants.js +++ b/app/assets/javascripts/sidebar/constants.js @@ -130,6 +130,11 @@ export const subscribedQueries = { }, }; +export const Tracking = { + editEvent: 'click_edit_button', + rightSidebarLabel: 'right_sidebar', +}; + export const timeTrackingQueries = { [IssuableType.Issue]: { query: issueTimeTrackingQuery, diff --git a/app/models/container_repository.rb b/app/models/container_repository.rb index 2d28a81f462..ab895438191 100644 --- a/app/models/container_repository.rb +++ b/app/models/container_repository.rb @@ -153,7 +153,8 @@ class ContainerRepository < ApplicationRecord end def self.create_from_path!(path) - build_from_path(path).tap(&:save!) + safe_find_or_create_by!(project: path.repository_project, + name: path.repository_name) end def self.build_root_repository(project) diff --git a/doc/user/application_security/dast/browser_based.md b/doc/user/application_security/dast/browser_based.md index 17773492fa3..1288db21880 100644 --- a/doc/user/application_security/dast/browser_based.md +++ b/doc/user/application_security/dast/browser_based.md @@ -21,7 +21,7 @@ Crawling continues by taking more snapshots and finding subsequent actions. The benefit of crawling by following user actions in a browser is that the crawler can interact with the target application much like a real user would, identifying complex flows that traditional web crawlers don’t understand. This results in better coverage of the website. -Scanning a web application with both the browser-based crawler and GitLab DAST should provide greater coverage, compared with only GitLab DAST. The new crawler does not support API scanning or the DAST AJAX crawler. +Using the browser-based crawler should provide greater coverage for most web applications, compared with the current DAST AJAX crawler. The new crawler replaces the AJAX crawler and is specifically designed to maximize crawl coverage in modern web applications. While both crawlers are currently used in conjunction with the existing DAST scanner, the combination of the browser-based crawler with the current DAST scanner is much more effective at finding and testing every page in an application. ## Enable browser-based crawler diff --git a/spec/frontend/content_editor/components/wrappers/image_spec.js b/spec/frontend/content_editor/components/wrappers/image_spec.js new file mode 100644 index 00000000000..7b057f9cabc --- /dev/null +++ b/spec/frontend/content_editor/components/wrappers/image_spec.js @@ -0,0 +1,66 @@ +import { GlLoadingIcon } from '@gitlab/ui'; +import { NodeViewWrapper } from '@tiptap/vue-2'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import ImageWrapper from '~/content_editor/components/wrappers/image.vue'; + +describe('content/components/wrappers/image', () => { + let wrapper; + + const createWrapper = async (nodeAttrs = {}) => { + wrapper = shallowMountExtended(ImageWrapper, { + propsData: { + node: { + attrs: nodeAttrs, + }, + }, + }); + }; + const findImage = () => wrapper.findByTestId('image'); + const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); + + afterEach(() => { + wrapper.destroy(); + }); + + it('renders a node-view-wrapper with display-inline-block class', () => { + createWrapper(); + + expect(wrapper.findComponent(NodeViewWrapper).classes()).toContain('gl-display-inline-block'); + }); + + it('renders an image that displays the node src', () => { + const src = 'foobar.png'; + + createWrapper({ src }); + + expect(findImage().attributes().src).toBe(src); + }); + + describe('when uploading', () => { + beforeEach(() => { + createWrapper({ uploading: true }); + }); + + it('renders a gl-loading-icon component', () => { + expect(findLoadingIcon().exists()).toBe(true); + }); + + it('adds gl-opacity-5 class selector to image', () => { + expect(findImage().classes()).toContain('gl-opacity-5'); + }); + }); + + describe('when not uploading', () => { + beforeEach(() => { + createWrapper({ uploading: false }); + }); + + it('does not render a gl-loading-icon component', () => { + expect(findLoadingIcon().exists()).toBe(false); + }); + + it('does not add gl-opacity-5 class selector to image', () => { + expect(findImage().classes()).not.toContain('gl-opacity-5'); + }); + }); +}); diff --git a/spec/models/container_repository_spec.rb b/spec/models/container_repository_spec.rb index 3232a559d0b..ec347006836 100644 --- a/spec/models/container_repository_spec.rb +++ b/spec/models/container_repository_spec.rb @@ -281,6 +281,16 @@ RSpec.describe ContainerRepository do expect(repository.name).to be_empty end end + + context 'when repository already exists' do + let(:path) { project.full_path + '/some/image' } + + it 'returns the existing repository' do + container_repository = create(:container_repository, project: project, name: 'some/image') + + expect(repository.id).to eq(container_repository.id) + end + end end describe '.build_root_repository' do |