diff options
author | John T Skarbek <jskarbek@gitlab.com> | 2019-04-30 19:18:49 -0400 |
---|---|---|
committer | John T Skarbek <jskarbek@gitlab.com> | 2019-04-30 19:18:49 -0400 |
commit | 6c07afabc9680d407c9f05c6daa136f0dfa52292 (patch) | |
tree | e36351907cf9dc7d7a1cbc08c6b983c8316a2bdb | |
parent | 3d81a2d2f3f17b2816c965c707a13cbf1c974ad3 (diff) | |
parent | e9a60068149c50a21e1759c21a7b6fa2f08e4741 (diff) | |
download | gitlab-ce-6c07afabc9680d407c9f05c6daa136f0dfa52292.tar.gz |
Merge remote-tracking branch 'origin/11-10-stable' into 11-10-stable
58 files changed, 512 insertions, 87 deletions
diff --git a/.stylelintrc b/.stylelintrc index 241d2c94a88..59ee0e879e6 100644 --- a/.stylelintrc +++ b/.stylelintrc @@ -64,7 +64,7 @@ "number-leading-zero":"always", "number-no-trailing-zeros":true, "property-no-unknown":true, - "property-no-vendor-prefix":true, + "property-no-vendor-prefix": [true, { "ignoreProperties": ["user-select"] }], "rule-empty-line-before":[ "always-multi-line", { diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION index f9c71a52e2f..85e2cd53092 100644 --- a/GITLAB_WORKHORSE_VERSION +++ b/GITLAB_WORKHORSE_VERSION @@ -1 +1 @@ -8.5.1 +8.5.2 diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue index f2bd4150b6d..00547abd7bc 100644 --- a/app/assets/javascripts/monitoring/components/dashboard.vue +++ b/app/assets/javascripts/monitoring/components/dashboard.vue @@ -221,6 +221,7 @@ export default { <gl-dropdown-item v-for="environment in store.environmentsData" :key="environment.id" + :href="environment.metrics_path" :active="environment.name === currentEnvironmentName" active-class="is-active" >{{ environment.name }}</gl-dropdown-item diff --git a/app/assets/javascripts/monitoring/monitoring_bundle.js b/app/assets/javascripts/monitoring/monitoring_bundle.js index ed794779ff2..08dc57d545c 100644 --- a/app/assets/javascripts/monitoring/monitoring_bundle.js +++ b/app/assets/javascripts/monitoring/monitoring_bundle.js @@ -1,6 +1,6 @@ import Vue from 'vue'; import { parseBoolean } from '~/lib/utils/common_utils'; -import Dashboard from './components/dashboard.vue'; +import Dashboard from 'ee_else_ce/monitoring/components/dashboard.vue'; export default (props = {}) => { const el = document.getElementById('prometheus-graphs'); diff --git a/app/assets/javascripts/mr_popover/index.js b/app/assets/javascripts/mr_popover/index.js index 9a97e98f9db..18c0e201300 100644 --- a/app/assets/javascripts/mr_popover/index.js +++ b/app/assets/javascripts/mr_popover/index.js @@ -22,13 +22,10 @@ const handleUserPopoverMouseOut = ({ target }) => { * Adds a MergeRequestPopover component to the body, hands over as much data as the target element has in data attributes. * loads based on data-project-path and data-iid more data about an MR from the API and sets it on the popover */ -const handleMRPopoverMount = apolloProvider => ({ target }) => { +const handleMRPopoverMount = ({ apolloProvider, projectPath, mrTitle, iid }) => ({ target }) => { // Add listener to actually remove it again target.addEventListener('mouseleave', handleUserPopoverMouseOut); - const { projectPath, mrTitle, iid } = target.dataset; - const mergeRequest = {}; - renderFn = setTimeout(() => { const MRPopoverComponent = Vue.extend(MRPopover); renderedPopover = new MRPopoverComponent({ @@ -36,7 +33,6 @@ const handleMRPopoverMount = apolloProvider => ({ target }) => { target, projectPath, mergeRequestIID: iid, - mergeRequest, mergeRequestTitle: mrTitle, }, apolloProvider, @@ -57,8 +53,13 @@ export default elements => { const listenerAddedAttr = 'data-mr-listener-added'; mrLinks.forEach(el => { - if (!el.getAttribute(listenerAddedAttr)) { - el.addEventListener('mouseenter', handleMRPopoverMount(apolloProvider)); + const { projectPath, mrTitle, iid } = el.dataset; + + if (!el.getAttribute(listenerAddedAttr) && projectPath && mrTitle && iid) { + el.addEventListener( + 'mouseenter', + handleMRPopoverMount({ apolloProvider, projectPath, mrTitle, iid }), + ); el.setAttribute(listenerAddedAttr, true); } }); diff --git a/app/assets/javascripts/pipelines/pipeline_details_bundle.js b/app/assets/javascripts/pipelines/pipeline_details_bundle.js index 6660f8120f8..b8976f77bac 100644 --- a/app/assets/javascripts/pipelines/pipeline_details_bundle.js +++ b/app/assets/javascripts/pipelines/pipeline_details_bundle.js @@ -34,6 +34,7 @@ export default () => { props: { isLoading: this.mediator.state.isLoading, pipeline: this.mediator.store.state.pipeline, + mediator: this.mediator, }, on: { refreshPipelineGraph: this.requestRefreshPipelineGraph, diff --git a/app/assets/javascripts/vue_shared/components/notes/system_note.vue b/app/assets/javascripts/vue_shared/components/notes/system_note.vue index acc179b3834..3c86b7e4c61 100644 --- a/app/assets/javascripts/vue_shared/components/notes/system_note.vue +++ b/app/assets/javascripts/vue_shared/components/notes/system_note.vue @@ -22,6 +22,7 @@ import noteHeader from '~/notes/components/note_header.vue'; import Icon from '~/vue_shared/components/icon.vue'; import TimelineEntryItem from './timeline_entry_item.vue'; import { spriteIcon } from '../../../lib/utils/common_utils'; +import initMRPopovers from '~/mr_popover/'; const MAX_VISIBLE_COMMIT_LIST_COUNT = 3; @@ -71,6 +72,9 @@ export default { ); }, }, + mounted() { + initMRPopovers(this.$el.querySelectorAll('.gfm-merge_request')); + }, }; </script> diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss index fc1c1bd9962..037ca9f954a 100644 --- a/app/assets/stylesheets/pages/boards.scss +++ b/app/assets/stylesheets/pages/boards.scss @@ -11,6 +11,9 @@ opacity: 1 !important; * { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; user-select: none; // !important to make sure no style can override this when dragging cursor: grabbing !important; diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss index 20bdc6596e9..0c99ff5341c 100644 --- a/app/assets/stylesheets/pages/search.scss +++ b/app/assets/stylesheets/pages/search.scss @@ -84,6 +84,9 @@ input[type='checkbox']:hover { .search-icon { transition: color $default-transition-duration; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; user-select: none; } diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index d1c5cef76fa..c4dff95a4b9 100644 --- a/app/controllers/projects/settings/ci_cd_controller.rb +++ b/app/controllers/projects/settings/ci_cd_controller.rb @@ -19,7 +19,7 @@ module Projects redirect_to project_settings_ci_cd_path(@project) else - render 'show' + redirect_to project_settings_ci_cd_path(@project), alert: result[:message] end end end diff --git a/app/helpers/markup_helper.rb b/app/helpers/markup_helper.rb index d83c69603a9..8aa96759ce5 100644 --- a/app/helpers/markup_helper.rb +++ b/app/helpers/markup_helper.rb @@ -4,7 +4,7 @@ require 'nokogiri' module MarkupHelper include ActionView::Helpers::TagHelper - include ActionView::Context + include ::Gitlab::ActionViewOutput::Context def plain?(filename) Gitlab::MarkupHelper.plain?(filename) @@ -83,7 +83,8 @@ module MarkupHelper text = sanitize( text, tags: tags, - attributes: Rails::Html::WhiteListSanitizer.allowed_attributes + ['style', 'data-src', 'data-name', 'data-unicode-version'] + attributes: Rails::Html::WhiteListSanitizer.allowed_attributes + + %w(style data-src data-name data-unicode-version data-iid data-project-path data-mr-title) ) # since <img> tags are stripped, this can leave empty <a> tags hanging around diff --git a/app/models/ci/bridge.rb b/app/models/ci/bridge.rb index 0d8d7d95791..644716ba8e7 100644 --- a/app/models/ci/bridge.rb +++ b/app/models/ci/bridge.rb @@ -4,6 +4,7 @@ module Ci class Bridge < CommitStatus include Ci::Processable include Ci::Contextable + include Ci::PipelineDelegator include Importable include AfterCommitQueue include HasRef @@ -13,8 +14,6 @@ module Ci belongs_to :trigger_request validates :ref, presence: true - delegate :merge_request_event?, to: :pipeline - def self.retry(bridge, current_user) raise NotImplementedError end diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 5cf9bb4979a..fc743475187 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -6,6 +6,7 @@ module Ci include Ci::Processable include Ci::Metadatable include Ci::Contextable + include Ci::PipelineDelegator include TokenAuthenticatable include AfterCommitQueue include ObjectStorage::BackgroundMove @@ -48,8 +49,6 @@ module Ci delegate :terminal_specification, to: :runner_session, allow_nil: true delegate :gitlab_deploy_token, to: :project delegate :trigger_short_token, to: :trigger_request, allow_nil: true - delegate :merge_request_event?, :merge_request_ref?, - :legacy_detached_merge_request_pipeline?, to: :pipeline ## # Since Gitlab 11.5, deployments records started being created right after diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index fd65b2c733a..4534ba49c0d 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -754,6 +754,22 @@ module Ci self.sha == sha || self.source_sha == sha end + def triggered_by?(current_user) + user == current_user + end + + def source_ref + if triggered_by_merge_request? + merge_request.source_branch + else + ref + end + end + + def source_ref_slug + Gitlab::Utils.slugify(source_ref.to_s) + end + private def ci_yaml_from_repo diff --git a/app/models/concerns/ci/contextable.rb b/app/models/concerns/ci/contextable.rb index 4986a42dbd2..e1d5ce7f7d4 100644 --- a/app/models/concerns/ci/contextable.rb +++ b/app/models/concerns/ci/contextable.rb @@ -70,8 +70,8 @@ module Ci variables.append(key: 'CI_COMMIT_SHA', value: sha) variables.append(key: 'CI_COMMIT_SHORT_SHA', value: short_sha) variables.append(key: 'CI_COMMIT_BEFORE_SHA', value: before_sha) - variables.append(key: 'CI_COMMIT_REF_NAME', value: ref) - variables.append(key: 'CI_COMMIT_REF_SLUG', value: ref_slug) + variables.append(key: 'CI_COMMIT_REF_NAME', value: source_ref) + variables.append(key: 'CI_COMMIT_REF_SLUG', value: source_ref_slug) variables.append(key: "CI_COMMIT_TAG", value: ref) if tag? variables.append(key: "CI_PIPELINE_TRIGGERED", value: 'true') if trigger_request variables.append(key: "CI_JOB_MANUAL", value: 'true') if action? @@ -85,8 +85,8 @@ module Ci Gitlab::Ci::Variables::Collection.new.tap do |variables| variables.append(key: 'CI_BUILD_REF', value: sha) variables.append(key: 'CI_BUILD_BEFORE_SHA', value: before_sha) - variables.append(key: 'CI_BUILD_REF_NAME', value: ref) - variables.append(key: 'CI_BUILD_REF_SLUG', value: ref_slug) + variables.append(key: 'CI_BUILD_REF_NAME', value: source_ref) + variables.append(key: 'CI_BUILD_REF_SLUG', value: source_ref_slug) variables.append(key: 'CI_BUILD_NAME', value: name) variables.append(key: 'CI_BUILD_STAGE', value: stage) variables.append(key: "CI_BUILD_TAG", value: ref) if tag? diff --git a/app/models/concerns/ci/pipeline_delegator.rb b/app/models/concerns/ci/pipeline_delegator.rb new file mode 100644 index 00000000000..dbc5ed1bc9a --- /dev/null +++ b/app/models/concerns/ci/pipeline_delegator.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +## +# This module is mainly used by child associations of `Ci::Pipeline` that needs to look up +# single source of truth. For example, `Ci::Build` has `git_ref` method, which behaves +# slightly different from `Ci::Pipeline`'s `git_ref`. This is very confusing as +# the system could behave differently time to time. +# We should have a single interface in `Ci::Pipeline` and access the method always. +module Ci + module PipelineDelegator + extend ActiveSupport::Concern + + included do + delegate :merge_request_event?, + :merge_request_ref?, + :source_ref, + :source_ref_slug, + :legacy_detached_merge_request_pipeline?, to: :pipeline + end + end +end diff --git a/app/models/concerns/has_ref.rb b/app/models/concerns/has_ref.rb index 413cd36dcaa..fa0cf5ddfd2 100644 --- a/app/models/concerns/has_ref.rb +++ b/app/models/concerns/has_ref.rb @@ -1,5 +1,8 @@ # frozen_string_literal: true +## +# We will disable `ref` and `sha` attributes in `Ci::Build` in the future +# and remove this module in favor of Ci::PipelineDelegator. module HasRef extend ActiveSupport::Concern diff --git a/app/models/deployment.rb b/app/models/deployment.rb index d847a0a11e4..332cd87c97a 100644 --- a/app/models/deployment.rb +++ b/app/models/deployment.rb @@ -79,7 +79,11 @@ class Deployment < ApplicationRecord end def cluster - project.deployment_platform(environment: environment.name)&.cluster + platform = project.deployment_platform(environment: environment.name) + + if platform.present? && platform.respond_to?(:cluster) + platform.cluster + end end def last? diff --git a/app/serializers/concerns/user_status_tooltip.rb b/app/serializers/concerns/user_status_tooltip.rb index 633b117d392..a81e377691e 100644 --- a/app/serializers/concerns/user_status_tooltip.rb +++ b/app/serializers/concerns/user_status_tooltip.rb @@ -3,7 +3,7 @@ module UserStatusTooltip extend ActiveSupport::Concern include ActionView::Helpers::TagHelper - include ActionView::Context + include ::Gitlab::ActionViewOutput::Context include EmojiHelper include UsersHelper diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml index 5b25a67bc87..8ae2807729b 100644 --- a/app/views/search/_results.html.haml +++ b/app/views/search/_results.html.haml @@ -21,10 +21,9 @@ - if @scope == 'projects' .term = render 'shared/projects/list', projects: @search_objects, pipeline_status: false - - elsif %w[blobs wiki_blobs].include?(@scope) - = render partial: 'search/results/blob', collection: @search_objects, locals: { projects: blob_projects(@search_objects) } - else - = render partial: "search/results/#{@scope.singularize}", collection: @search_objects + - locals = { projects: blob_projects(@search_objects) } if %w[blobs wiki_blobs].include?(@scope) + = render partial: "search/results/#{@scope.singularize}", collection: @search_objects, locals: locals - if @scope != 'projects' = paginate_collection(@search_objects) diff --git a/app/workers/pipeline_schedule_worker.rb b/app/workers/pipeline_schedule_worker.rb index 02a69ea3b54..8a9ee7808e4 100644 --- a/app/workers/pipeline_schedule_worker.rb +++ b/app/workers/pipeline_schedule_worker.rb @@ -3,20 +3,26 @@ class PipelineScheduleWorker include ApplicationWorker include CronjobQueue + include ::Gitlab::ExclusiveLeaseHelpers + + EXCLUSIVE_LOCK_KEY = 'pipeline_schedules:run:lock' + LOCK_TIMEOUT = 50.minutes # rubocop: disable CodeReuse/ActiveRecord def perform - Ci::PipelineSchedule.active.where("next_run_at < ?", Time.now) - .preload(:owner, :project).find_each do |schedule| - - Ci::CreatePipelineService.new(schedule.project, - schedule.owner, - ref: schedule.ref) - .execute!(:schedule, ignore_skip_ci: true, save_on_errors: true, schedule: schedule) - rescue => e - error(schedule, e) - ensure - schedule.schedule_next_run! + in_lock(EXCLUSIVE_LOCK_KEY, ttl: LOCK_TIMEOUT, retries: 1) do + Ci::PipelineSchedule.active.where("next_run_at < ?", Time.now) + .preload(:owner, :project).find_each do |schedule| + + schedule.schedule_next_run! + + Ci::CreatePipelineService.new(schedule.project, + schedule.owner, + ref: schedule.ref) + .execute!(:schedule, ignore_skip_ci: true, save_on_errors: true, schedule: schedule) + rescue => e + error(schedule, e) + end end end # rubocop: enable CodeReuse/ActiveRecord diff --git a/changelogs/unreleased/54656-500-error-on-save-of-general-pipeline-settings-timeout.yml b/changelogs/unreleased/54656-500-error-on-save-of-general-pipeline-settings-timeout.yml new file mode 100644 index 00000000000..8b4f4894048 --- /dev/null +++ b/changelogs/unreleased/54656-500-error-on-save-of-general-pipeline-settings-timeout.yml @@ -0,0 +1,5 @@ +--- +title: Fix 500 in general pipeline settings when passing an invalid build timeout. +merge_request: 27416 +author: +type: fixed diff --git a/changelogs/unreleased/60540-merge-request-popover-is-not-working-on-the-to-do-page.yml b/changelogs/unreleased/60540-merge-request-popover-is-not-working-on-the-to-do-page.yml new file mode 100644 index 00000000000..7b5fae016bb --- /dev/null +++ b/changelogs/unreleased/60540-merge-request-popover-is-not-working-on-the-to-do-page.yml @@ -0,0 +1,5 @@ +--- +title: Fix MR popover on ToDos page +merge_request: 27382 +author: +type: fixed diff --git a/changelogs/unreleased/60687-enviro-dropdown.yml b/changelogs/unreleased/60687-enviro-dropdown.yml new file mode 100644 index 00000000000..1fc5a7dd6f5 --- /dev/null +++ b/changelogs/unreleased/60687-enviro-dropdown.yml @@ -0,0 +1,5 @@ +--- +title: Fix Metrics Environments dropdown +merge_request: +author: +type: fixed diff --git a/changelogs/unreleased/60821-deployment-jobs-broken-as-of-11-10-0.yml b/changelogs/unreleased/60821-deployment-jobs-broken-as-of-11-10-0.yml new file mode 100644 index 00000000000..88584352d42 --- /dev/null +++ b/changelogs/unreleased/60821-deployment-jobs-broken-as-of-11-10-0.yml @@ -0,0 +1,5 @@ +--- +title: Fix Kubernetes service template deployment jobs broken as of 11.10.0 +merge_request: 27687 +author: +type: fixed diff --git a/changelogs/unreleased/60855-mr-popover-is-not-attached-in-system-notes.yml b/changelogs/unreleased/60855-mr-popover-is-not-attached-in-system-notes.yml new file mode 100644 index 00000000000..f7017ddf3dd --- /dev/null +++ b/changelogs/unreleased/60855-mr-popover-is-not-attached-in-system-notes.yml @@ -0,0 +1,5 @@ +--- +title: Fix bug where system note MR has no popover +merge_request: 27589 +author: +type: fixed diff --git a/changelogs/unreleased/60906-fix-wiki-links.yml b/changelogs/unreleased/60906-fix-wiki-links.yml new file mode 100644 index 00000000000..cc65a1382bf --- /dev/null +++ b/changelogs/unreleased/60906-fix-wiki-links.yml @@ -0,0 +1,5 @@ +--- +title: Show proper wiki links in search results +merge_request: 27634 +author: +type: fixed diff --git a/changelogs/unreleased/fix-ci-commit-ref-name-and-slug.yml b/changelogs/unreleased/fix-ci-commit-ref-name-and-slug.yml new file mode 100644 index 00000000000..c34bc6d8b52 --- /dev/null +++ b/changelogs/unreleased/fix-ci-commit-ref-name-and-slug.yml @@ -0,0 +1,5 @@ +--- +title: Make `CI_COMMIT_REF_NAME` and `SLUG` variable idempotent +merge_request: 27663 +author: +type: fixed diff --git a/changelogs/unreleased/fj-60827-fix-web-strategy-error.yml b/changelogs/unreleased/fj-60827-fix-web-strategy-error.yml new file mode 100644 index 00000000000..ad707ca0225 --- /dev/null +++ b/changelogs/unreleased/fj-60827-fix-web-strategy-error.yml @@ -0,0 +1,5 @@ +--- +title: Fix bug when project export to remote url fails +merge_request: 27614 +author: +type: fixed diff --git a/changelogs/unreleased/lock-pipeline-schedule-worker.yml b/changelogs/unreleased/lock-pipeline-schedule-worker.yml new file mode 100644 index 00000000000..1b889f01620 --- /dev/null +++ b/changelogs/unreleased/lock-pipeline-schedule-worker.yml @@ -0,0 +1,5 @@ +--- +title: Prevent concurrent execution of PipelineScheduleWorker +merge_request: 27781 +author: +type: performance diff --git a/changelogs/unreleased/sh-fix-slow-partial-rendering.yml b/changelogs/unreleased/sh-fix-slow-partial-rendering.yml new file mode 100644 index 00000000000..0f65a6f8d69 --- /dev/null +++ b/changelogs/unreleased/sh-fix-slow-partial-rendering.yml @@ -0,0 +1,5 @@ +--- +title: Fix slow performance with compiling HAML templates +merge_request: 27782 +author: +type: performance diff --git a/changelogs/unreleased/update-workhorse-11-10.yml b/changelogs/unreleased/update-workhorse-11-10.yml new file mode 100644 index 00000000000..5172a2860f3 --- /dev/null +++ b/changelogs/unreleased/update-workhorse-11-10.yml @@ -0,0 +1,5 @@ +--- +title: Update Workhorse to v8.5.2 +merge_request: 27631 +author: +type: fixed diff --git a/changelogs/unreleased/winh-boards-drag-selection.yml b/changelogs/unreleased/winh-boards-drag-selection.yml new file mode 100644 index 00000000000..84b23ab664b --- /dev/null +++ b/changelogs/unreleased/winh-boards-drag-selection.yml @@ -0,0 +1,5 @@ +--- +title: Prevent text selection when dragging in issue boards +merge_request: 27724 +author: +type: fixed diff --git a/doc/administration/high_availability/nfs.md b/doc/administration/high_availability/nfs.md index f406163aea0..9d956b84426 100644 --- a/doc/administration/high_availability/nfs.md +++ b/doc/administration/high_availability/nfs.md @@ -39,7 +39,14 @@ options: ### Improving NFS performance with GitLab -NOTE: **Note:** This is only available with GitLab 11.9 and up. +NOTE: **Note:** +This is only available starting in certain versions of GitLab: + + * 11.5.11 + * 11.6.11 + * 11.7.12 + * 11.8.8 + * 11.9.0 and up (e.g. 11.10, 11.11, etc.) If you are using NFS to share Git data, we recommend that you enable a number of feature flags that will allow GitLab application processes to diff --git a/lib/gitlab/action_view_output/context.rb b/lib/gitlab/action_view_output/context.rb new file mode 100644 index 00000000000..9fbc9811636 --- /dev/null +++ b/lib/gitlab/action_view_output/context.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +# This file was simplified from https://raw.githubusercontent.com/rails/rails/195f39804a7a4a0034f25e8704220e03d95a752a/actionview/lib/action_view/context.rb. +# +# It is only needed by modules that need to call ActionView helper +# methods (e.g. those in +# https://github.com/rails/rails/tree/c4d3e202e10ae627b3b9c34498afb45450652421/actionview/lib/action_view/helpers) +# to generate tags outside of a Rails controller (e.g. API, Sidekiq, +# etc.). +# +# In Rails 5, ActionView::Context automatically includes CompiledTemplates. +# This means that any module that includes ActionView::Context is now a descendant +# of CompiledTemplates. +# +# When a partial is rendered for the first time, it runs +# Module#module_eval, which will evaluate a string source that defines a +# new method. For example: +# +# def _app_views_profiles_show_html_haml___1285955918103175884_70307801785400(local_assigns, output_buffer) +# "hello world" +# end +# +# When a new method is defined, the Ruby interpreter clears the method +# cache for all descendants, and all methods for those modules will have +# to be redefined. This can lead to a significant performance penalty. +# +# Rails 6 fixes this behavior by moving out the `include +# CompiledTemplates` into ActionView::Base so that including `ActionView::Context` +# doesn't quietly affect other modules in this way. + +if Rails::VERSION::STRING.start_with?('6') + raise 'This module is no longer needed in Rails 6. Use ActionView::Context instead.' +end + +module Gitlab + module ActionViewOutput + module Context + attr_accessor :output_buffer, :view_flow + end + end +end diff --git a/lib/gitlab/checks/lfs_check.rb b/lib/gitlab/checks/lfs_check.rb index cc6a14d2d9a..67a65d61441 100644 --- a/lib/gitlab/checks/lfs_check.rb +++ b/lib/gitlab/checks/lfs_check.rb @@ -7,6 +7,7 @@ module Gitlab ERROR_MESSAGE = 'LFS objects are missing. Ensure LFS is properly set up or try a manual "git lfs push --all".'.freeze def validate! + return unless Feature.enabled?(:lfs_check, default_enabled: true) return unless project.lfs_enabled? return if skip_lfs_integrity_check diff --git a/lib/gitlab/ci/variables/collection/item.rb b/lib/gitlab/ci/variables/collection/item.rb index 833aa75adb5..aab10aef398 100644 --- a/lib/gitlab/ci/variables/collection/item.rb +++ b/lib/gitlab/ci/variables/collection/item.rb @@ -27,13 +27,9 @@ module Gitlab # don't expose `file` attribute at all (stems from what the runner # expects). # - # If the `variable_masking` feature is enabled we expose the `masked` - # attribute, otherwise it's not exposed. - # def to_runner_variable @variable.reject do |hash_key, hash_value| - (hash_key == :file && hash_value == false) || - (hash_key == :masked && !Feature.enabled?(:variable_masking)) + hash_key == :file && hash_value == false end end diff --git a/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb b/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb index b30900f7c61..7a057d79921 100644 --- a/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb +++ b/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb @@ -30,10 +30,7 @@ module Gitlab def handle_response_error(response) unless response.success? - error_code = response.dig('Error', 'Code') || response.code - error_message = response.dig('Error', 'Message') || response.message - - raise StrategyError.new("Error uploading the project. Code #{error_code}: #{error_message}") + raise StrategyError.new("Error uploading the project. Code #{response.code}: #{response.message}") end end diff --git a/package.json b/package.json index 6d3e6764a46..888faa829a8 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@babel/preset-env": "^7.3.1", "@gitlab/csslab": "^1.9.0", "@gitlab/svgs": "^1.58.0", - "@gitlab/ui": "^3.2.0", + "@gitlab/ui": "3.2.0-hotfix.1", "apollo-cache-inmemory": "^1.5.1", "apollo-client": "^2.5.1", "apollo-upload-client": "^10.0.0", diff --git a/rubocop/cop/include_action_view_context.rb b/rubocop/cop/include_action_view_context.rb new file mode 100644 index 00000000000..14662a33e95 --- /dev/null +++ b/rubocop/cop/include_action_view_context.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require_relative '../spec_helpers' + +module RuboCop + module Cop + # Cop that makes sure workers include `::Gitlab::ActionViewOutput::Context`, not `ActionView::Context`. + class IncludeActionViewContext < RuboCop::Cop::Cop + include SpecHelpers + + MSG = 'Include `::Gitlab::ActionViewOutput::Context`, not `ActionView::Context`, for Rails 5.'.freeze + + def_node_matcher :includes_action_view_context?, <<~PATTERN + (send nil? :include (const (const nil? :ActionView) :Context)) + PATTERN + + def on_send(node) + return if in_spec?(node) + return unless includes_action_view_context?(node) + + add_offense(node.arguments.first, location: :expression) + end + + def autocorrect(node) + lambda do |corrector| + corrector.replace(node.source_range, '::Gitlab::ActionViewOutput::Context') + end + end + end + end +end diff --git a/rubocop/rubocop.rb b/rubocop/rubocop.rb index 3e33419eb2e..f36d88d4a40 100644 --- a/rubocop/rubocop.rb +++ b/rubocop/rubocop.rb @@ -4,6 +4,7 @@ require_relative 'cop/gitlab/predicate_memoization' require_relative 'cop/gitlab/httparty' require_relative 'cop/gitlab/finder_with_find_by' require_relative 'cop/gitlab/union' +require_relative 'cop/include_action_view_context' require_relative 'cop/include_sidekiq_worker' require_relative 'cop/safe_params' require_relative 'cop/avoid_return_from_blocks' diff --git a/spec/controllers/projects/settings/ci_cd_controller_spec.rb b/spec/controllers/projects/settings/ci_cd_controller_spec.rb index 41cc0607cee..1b5dcc6ff52 100644 --- a/spec/controllers/projects/settings/ci_cd_controller_spec.rb +++ b/spec/controllers/projects/settings/ci_cd_controller_spec.rb @@ -189,6 +189,15 @@ describe Projects::Settings::CiCdController do expect(project.build_timeout).to eq(5400) end end + + context 'when build_timeout_human_readable is invalid' do + let(:params) { { build_timeout_human_readable: '5m' } } + + it 'set specified timeout' do + expect(subject).to set_flash[:alert] + expect(response).to redirect_to(namespace_project_settings_ci_cd_path) + end + end end end end diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb index 752d6ae55cc..5d59a0aeae9 100644 --- a/spec/controllers/search_controller_spec.rb +++ b/spec/controllers/search_controller_spec.rb @@ -9,6 +9,30 @@ describe SearchController do sign_in(user) end + context 'uses the right partials depending on scope' do + using RSpec::Parameterized::TableSyntax + render_views + + set(:project) { create(:project, :public, :repository, :wiki_repo) } + + subject { get(:show, params: { project_id: project.id, scope: scope, search: 'merge' }) } + + where(:partial, :scope) do + '_blob' | :blobs + '_wiki_blob' | :wiki_blobs + '_commit' | :commits + end + + with_them do + it do + project_wiki = create(:project_wiki, project: project, user: user) + create(:wiki_page, wiki: project_wiki, attrs: { title: 'merge', content: 'merge' }) + + expect(subject).to render_template("search/results/#{partial}") + end + end + end + it 'finds issue comments' do project = create(:project, :public) note = create(:note_on_issue, project: project) diff --git a/spec/features/dashboard/todos/todos_spec.rb b/spec/features/dashboard/todos/todos_spec.rb index fd8677feab5..d58e3b2841e 100644 --- a/spec/features/dashboard/todos/todos_spec.rb +++ b/spec/features/dashboard/todos/todos_spec.rb @@ -17,6 +17,26 @@ describe 'Dashboard Todos' do end end + context 'when the todo references a merge request' do + let(:referenced_mr) { create(:merge_request, source_project: project) } + let(:note) { create(:note, project: project, note: "Check out #{referenced_mr.to_reference}") } + let!(:todo) { create(:todo, :mentioned, user: user, project: project, author: author, note: note) } + + before do + sign_in(user) + visit dashboard_todos_path + end + + it 'renders the mr link with the extra attributes' do + link = page.find_link(referenced_mr.to_reference) + + expect(link).not_to be_nil + expect(link['data-iid']).to eq(referenced_mr.iid.to_s) + expect(link['data-project-path']).to eq(referenced_mr.project.full_path) + expect(link['data-mr-title']).to eq(referenced_mr.title) + end + end + context 'User has a todo', :js do before do create(:todo, :mentioned, user: user, project: project, target: issue, author: author) diff --git a/spec/frontend/mr_popover/index_spec.js b/spec/frontend/mr_popover/index_spec.js index 8c33e52a04b..b9db2342687 100644 --- a/spec/frontend/mr_popover/index_spec.js +++ b/spec/frontend/mr_popover/index_spec.js @@ -7,18 +7,28 @@ createDefaultClient.default = jest.fn(); describe('initMRPopovers', () => { let mr1; let mr2; + let mr3; beforeEach(() => { setHTMLFixture(` - <div id="one" class="gfm-merge_request">MR1</div> - <div id="two" class="gfm-merge_request">MR2</div> + <div id="one" class="gfm-merge_request" data-mr-title="title" data-iid="1" data-project-path="group/project"> + MR1 + </div> + <div id="two" class="gfm-merge_request" data-mr-title="title" data-iid="1" data-project-path="group/project"> + MR2 + </div> + <div id="three" class="gfm-merge_request"> + MR3 + </div> `); mr1 = document.querySelector('#one'); mr2 = document.querySelector('#two'); + mr3 = document.querySelector('#three'); mr1.addEventListener = jest.fn(); mr2.addEventListener = jest.fn(); + mr3.addEventListener = jest.fn(); }); it('does not add the same event listener twice', () => { @@ -27,4 +37,10 @@ describe('initMRPopovers', () => { expect(mr1.addEventListener).toHaveBeenCalledTimes(1); expect(mr2.addEventListener).toHaveBeenCalledTimes(1); }); + + it('does not add listener if it does not have the necessary data attributes', () => { + initMRPopovers([mr1, mr2, mr3]); + + expect(mr3.addEventListener).not.toHaveBeenCalled(); + }); }); diff --git a/spec/javascripts/monitoring/dashboard_spec.js b/spec/javascripts/monitoring/dashboard_spec.js index ce2c6c43c0f..16dc0084a10 100644 --- a/spec/javascripts/monitoring/dashboard_spec.js +++ b/spec/javascripts/monitoring/dashboard_spec.js @@ -175,7 +175,7 @@ describe('Dashboard', () => { setTimeout(() => { const dropdownItems = component.$el.querySelectorAll( - '.js-environments-dropdown .dropdown-item[active="true"]', + '.js-environments-dropdown .dropdown-item.is-active', ); expect(dropdownItems.length).toEqual(1); diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_alert_message_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_alert_message_spec.js index f115cb457e5..8ec17efffb9 100644 --- a/spec/javascripts/vue_mr_widget/components/mr_widget_alert_message_spec.js +++ b/spec/javascripts/vue_mr_widget/components/mr_widget_alert_message_spec.js @@ -11,6 +11,7 @@ describe('MrWidgetAlertMessage', () => { wrapper = shallowMount(localVue.extend(MrWidgetAlertMessage), { propsData: {}, localVue, + sync: false, }); }); @@ -19,45 +20,58 @@ describe('MrWidgetAlertMessage', () => { }); describe('when type is not provided', () => { - it('should render a red message', () => { - expect(wrapper.classes()).toContain('danger_message'); - expect(wrapper.classes()).not.toContain('warning_message'); + it('should render a red message', done => { + wrapper.vm.$nextTick(() => { + expect(wrapper.classes()).toContain('danger_message'); + expect(wrapper.classes()).not.toContain('warning_message'); + done(); + }); }); }); describe('when type === "danger"', () => { - it('should render a red message', () => { + it('should render a red message', done => { wrapper.setProps({ type: 'danger' }); - - expect(wrapper.classes()).toContain('danger_message'); - expect(wrapper.classes()).not.toContain('warning_message'); + wrapper.vm.$nextTick(() => { + expect(wrapper.classes()).toContain('danger_message'); + expect(wrapper.classes()).not.toContain('warning_message'); + done(); + }); }); }); describe('when type === "warning"', () => { - it('should render a red message', () => { + it('should render a red message', done => { wrapper.setProps({ type: 'warning' }); - - expect(wrapper.classes()).toContain('warning_message'); - expect(wrapper.classes()).not.toContain('danger_message'); + wrapper.vm.$nextTick(() => { + expect(wrapper.classes()).toContain('warning_message'); + expect(wrapper.classes()).not.toContain('danger_message'); + done(); + }); }); }); describe('when helpPath is not provided', () => { - it('should not render a help icon/link', () => { - const link = wrapper.find(GlLink); + it('should not render a help icon/link', done => { + wrapper.vm.$nextTick(() => { + const link = wrapper.find(GlLink); - expect(link.exists()).toBe(false); + expect(link.exists()).toBe(false); + done(); + }); }); }); describe('when helpPath is provided', () => { - it('should render a help icon/link', () => { + it('should render a help icon/link', done => { wrapper.setProps({ helpPath: '/path/to/help/docs' }); - const link = wrapper.find(GlLink); + wrapper.vm.$nextTick(() => { + const link = wrapper.find(GlLink); - expect(link.exists()).toBe(true); - expect(link.attributes().href).toBe('/path/to/help/docs'); + expect(link.exists()).toBe(true); + expect(link.attributes().href).toBe('/path/to/help/docs'); + done(); + }); }); }); }); diff --git a/spec/javascripts/vue_shared/components/notes/system_note_spec.js b/spec/javascripts/vue_shared/components/notes/system_note_spec.js index adcb1c858aa..5b4ca20940a 100644 --- a/spec/javascripts/vue_shared/components/notes/system_note_spec.js +++ b/spec/javascripts/vue_shared/components/notes/system_note_spec.js @@ -5,8 +5,10 @@ import createStore from '~/notes/stores'; describe('system note component', () => { let vm; let props; + let initMRPopoversSpy; beforeEach(() => { + initMRPopoversSpy = spyOnDependency(issueSystemNote, 'initMRPopovers'); props = { note: { id: '1424', @@ -56,4 +58,8 @@ describe('system note component', () => { it('removes wrapping paragraph from note HTML', () => { expect(vm.$el.querySelector('.system-note-message').innerHTML).toEqual('<span>closed</span>'); }); + + it('should initMRPopovers onMount', () => { + expect(initMRPopoversSpy).toHaveBeenCalled(); + }); }); diff --git a/spec/lib/gitlab/checks/lfs_check_spec.rb b/spec/lib/gitlab/checks/lfs_check_spec.rb index 35f8069c8a4..dad14e100a7 100644 --- a/spec/lib/gitlab/checks/lfs_check_spec.rb +++ b/spec/lib/gitlab/checks/lfs_check_spec.rb @@ -27,6 +27,18 @@ describe Gitlab::Checks::LfsCheck do allow(project).to receive(:lfs_enabled?).and_return(true) end + context 'with lfs_check feature disabled' do + before do + stub_feature_flags(lfs_check: false) + end + + it 'skips integrity check' do + expect_any_instance_of(Gitlab::Git::LfsChanges).not_to receive(:new_pointers) + + subject.validate! + end + end + context 'deletion' do let(:changes) { { oldrev: oldrev, ref: ref } } diff --git a/spec/lib/gitlab/ci/variables/collection/item_spec.rb b/spec/lib/gitlab/ci/variables/collection/item_spec.rb index 3ff2fe18c15..613814df23f 100644 --- a/spec/lib/gitlab/ci/variables/collection/item_spec.rb +++ b/spec/lib/gitlab/ci/variables/collection/item_spec.rb @@ -137,19 +137,5 @@ describe Gitlab::Ci::Variables::Collection::Item do .to eq(key: 'VAR', value: 'value', public: true, file: true, masked: false) end end - - context 'when variable masking is disabled' do - before do - stub_feature_flags(variable_masking: false) - end - - it 'does not expose the masked field to the runner' do - runner_variable = described_class - .new(key: 'VAR', value: 'value', masked: true) - .to_runner_variable - - expect(runner_variable).to eq(key: 'VAR', value: 'value', public: true) - end - end end end diff --git a/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb b/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb index ec17ad8541f..7c4ac62790e 100644 --- a/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb +++ b/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb @@ -32,5 +32,17 @@ describe Gitlab::ImportExport::AfterExportStrategies::WebUploadStrategy do strategy.execute(user, project) end + + context 'when upload fails' do + it 'stores the export error' do + stub_request(:post, example_url).to_return(status: [404, 'Page not found']) + + strategy.execute(user, project) + + errors = project.import_export_shared.errors + expect(errors).not_to be_empty + expect(errors.first).to eq "Error uploading the project. Code 404: Page not found" + end + end end end diff --git a/spec/models/ci/bridge_spec.rb b/spec/models/ci/bridge_spec.rb index aacfbe3f180..913695f72a7 100644 --- a/spec/models/ci/bridge_spec.rb +++ b/spec/models/ci/bridge_spec.rb @@ -10,6 +10,8 @@ describe Ci::Bridge do create(:ci_bridge, pipeline: pipeline) end + it { is_expected.to include_module(Ci::PipelineDelegator) } + describe '#tags' do it 'only has a bridge tag' do expect(bridge.tags).to eq [:bridge] diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 66be192ab21..0e1be8809cb 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -28,6 +28,7 @@ describe Ci::Build do it { is_expected.to delegate_method(:merge_request_event?).to(:pipeline) } it { is_expected.to delegate_method(:merge_request_ref?).to(:pipeline) } it { is_expected.to delegate_method(:legacy_detached_merge_request_pipeline?).to(:pipeline) } + it { is_expected.to include_module(Ci::PipelineDelegator) } it { is_expected.to be_a(ArtifactMigratable) } @@ -2312,6 +2313,19 @@ describe Ci::Build do it { user_variables.each { |v| is_expected.to include(v) } } end + context 'when build belongs to a pipeline for merge request' do + let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline, source_branch: 'improve/awesome') } + let(:pipeline) { merge_request.all_pipelines.first } + let(:build) { create(:ci_build, ref: pipeline.ref, pipeline: pipeline) } + + it 'returns values based on source ref' do + is_expected.to include( + { key: 'CI_COMMIT_REF_NAME', value: 'improve/awesome', public: true, masked: false }, + { key: 'CI_COMMIT_REF_SLUG', value: 'improve-awesome', public: true, masked: false } + ) + end + end + context 'when build has an environment' do let(:environment_variables) do [ @@ -2703,6 +2717,8 @@ describe Ci::Build do ) end + let(:pipeline) { create(:ci_pipeline, project: project, ref: 'feature') } + it 'returns static predefined variables' do expect(build.variables.size).to be >= 28 expect(build.variables) @@ -2752,6 +2768,8 @@ describe Ci::Build do ) end + let(:pipeline) { create(:ci_pipeline, project: project, ref: 'feature') } + it 'does not persist the build' do expect(build).to be_valid expect(build).not_to be_persisted diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index f34aa0d9b03..9b80e45d9de 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -382,6 +382,54 @@ describe Ci::Pipeline, :mailer do end end + describe '#source_ref' do + subject { pipeline.source_ref } + + let(:pipeline) { create(:ci_pipeline, ref: 'feature') } + + it 'returns source ref' do + is_expected.to eq('feature') + end + + context 'when the pipeline is a detached merge request pipeline' do + let(:merge_request) { create(:merge_request) } + + let(:pipeline) do + create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, ref: merge_request.ref_path) + end + + it 'returns source ref' do + is_expected.to eq(merge_request.source_branch) + end + end + end + + describe '#source_ref_slug' do + subject { pipeline.source_ref_slug } + + let(:pipeline) { create(:ci_pipeline, ref: 'feature') } + + it 'slugifies with the source ref' do + expect(Gitlab::Utils).to receive(:slugify).with('feature') + + subject + end + + context 'when the pipeline is a detached merge request pipeline' do + let(:merge_request) { create(:merge_request) } + + let(:pipeline) do + create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, ref: merge_request.ref_path) + end + + it 'slugifies with the source ref of the merge request' do + expect(Gitlab::Utils).to receive(:slugify).with(merge_request.source_branch) + + subject + end + end + end + describe '.triggered_for_branch' do subject { described_class.triggered_for_branch(ref) } diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb index d9170d5fa07..be0cc58b35a 100644 --- a/spec/models/deployment_spec.rb +++ b/spec/models/deployment_spec.rb @@ -379,6 +379,12 @@ describe Deployment do it { is_expected.to be_nil } end + context 'project uses the kubernetes service for deployments' do + let!(:service) { create(:kubernetes_service, project: project) } + + it { is_expected.to be_nil } + end + context 'project has a deployment platform' do let!(:cluster) { create(:cluster, projects: [project]) } let!(:platform) { create(:cluster_platform_kubernetes, cluster: cluster) } diff --git a/spec/rubocop/cop/include_action_view_context_spec.rb b/spec/rubocop/cop/include_action_view_context_spec.rb new file mode 100644 index 00000000000..c888555b54f --- /dev/null +++ b/spec/rubocop/cop/include_action_view_context_spec.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +require 'spec_helper' + +require 'rubocop' +require 'rubocop/rspec/support' + +require_relative '../../../rubocop/cop/include_action_view_context' + +describe RuboCop::Cop::IncludeActionViewContext do + include CopHelper + + subject(:cop) { described_class.new } + + context 'when `ActionView::Context` is included' do + let(:source) { 'include ActionView::Context' } + let(:correct_source) { 'include ::Gitlab::ActionViewOutput::Context' } + + it 'registers an offense' do + inspect_source(source) + + aggregate_failures do + expect(cop.offenses.size).to eq(1) + expect(cop.offenses.map(&:line)).to eq([1]) + expect(cop.highlights).to eq(['ActionView::Context']) + end + end + + it 'autocorrects to the right version' do + autocorrected = autocorrect_source(source) + + expect(autocorrected).to eq(correct_source) + end + end + + context 'when `ActionView::Context` is not included' do + it 'registers no offense' do + inspect_source('include Context') + + aggregate_failures do + expect(cop.offenses.size).to eq(0) + end + end + end +end diff --git a/spec/workers/pipeline_schedule_worker_spec.rb b/spec/workers/pipeline_schedule_worker_spec.rb index f23910d23be..8c604b13297 100644 --- a/spec/workers/pipeline_schedule_worker_spec.rb +++ b/spec/workers/pipeline_schedule_worker_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' describe PipelineScheduleWorker do + include ExclusiveLeaseHelpers + subject { described_class.new.perform } set(:project) { create(:project, :repository) } @@ -39,6 +41,16 @@ describe PipelineScheduleWorker do it_behaves_like 'successful scheduling' + context 'when exclusive lease has already been taken by the other instance' do + before do + stub_exclusive_lease_taken(described_class::EXCLUSIVE_LOCK_KEY, timeout: described_class::LOCK_TIMEOUT) + end + + it 'raises an error and does not start creating pipelines' do + expect { subject }.to raise_error(Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError) + end + end + context 'when the latest commit contains [ci skip]' do before do allow_any_instance_of(Ci::Pipeline) diff --git a/yarn.lock b/yarn.lock index 571ac952e90..3e7e4275e45 100644 --- a/yarn.lock +++ b/yarn.lock @@ -663,10 +663,10 @@ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.58.0.tgz#bb05263ff2eb7ca09a25cd14d0b1a932d2ea9c2f" integrity sha512-RlWSjjBT4lMIFuNC1ziCO1nws9zqZtxCjhrqK2DxDDTgp2W0At9M/BFkHp8RHyMCrO3g1fHTrLPUgzr5oR3Epg== -"@gitlab/ui@^3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-3.2.0.tgz#3a44ac806a22b87fe45e6edfa410cb9355164f04" - integrity sha512-If2ngMIw0jWAdQ1q3PfB8sDhCXz1r3DsRm1X5Vy767kZ2TeFd7SGBp5KP5ceMGGpQ4TTYU/V8IqYnQbTXfPKRw== +"@gitlab/ui@3.2.0-hotfix.1": + version "3.2.0-hotfix.1" + resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-3.2.0-hotfix.1.tgz#80d3bab994b2a84fd9a61c8fdd06e5ca10547aa1" + integrity sha512-3og6WuXb5JDk+btAS3UuC8PGv/cdu2bisCQ/tpkD0QRNptit2Or96bGEH0hzKxAlSSEzFA3sZlhbxvg/vPLCRg== dependencies: "@babel/standalone" "^7.0.0" bootstrap-vue "^2.0.0-rc.11" |