Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab/issue_templates/Feature proposal.md4
-rw-r--r--CHANGELOG.md1
-rw-r--r--VERSION2
-rw-r--r--app/assets/javascripts/monitoring/components/charts/time_series.vue5
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/panel_type.vue7
-rw-r--r--app/assets/javascripts/notes.js24
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_table_row.vue1
-rw-r--r--app/views/layouts/nav/sidebar/_project.html.haml2
-rw-r--r--app/views/shared/_service_settings.html.haml2
-rw-r--r--babel.config.js1
-rw-r--r--changelogs/unreleased/194381-new-integrations-are-not-active-by-default.yml5
-rw-r--r--config/webpack.config.js2
-rw-r--r--doc/user/analytics/code_review_analytics.md25
-rw-r--r--jest.config.js2
-rw-r--r--package.json2
-rw-r--r--qa/qa.rb2
-rw-r--r--qa/qa/fixtures/monitored_auto_devops/.gitlab-ci.yml337
-rw-r--r--qa/qa/page/layout/performance_bar.rb4
-rw-r--r--qa/qa/page/project/operations/metrics.rb87
-rw-r--r--qa/qa/page/project/pipeline/index.rb22
-rw-r--r--qa/qa/page/project/sub_menus/operations.rb9
-rw-r--r--qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb6
-rw-r--r--spec/features/projects/services/user_activates_issue_tracker_spec.rb15
-rw-r--r--spec/features/projects/services/user_activates_jira_spec.rb8
-rw-r--r--spec/features/projects/services/user_activates_youtrack_spec.rb8
-rw-r--r--spec/features/projects/tree/create_directory_spec.rb7
-rw-r--r--spec/features/projects/tree/create_file_spec.rb7
-rw-r--r--spec/frontend/boards/issue_card_spec.js4
-rw-r--r--spec/frontend/error_tracking_settings/components/project_dropdown_spec.js12
-rw-r--r--spec/frontend/notes/old_notes_spec.js5
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js4
-rw-r--r--yarn.lock34
33 files changed, 575 insertions, 83 deletions
diff --git a/.gitlab/issue_templates/Feature proposal.md b/.gitlab/issue_templates/Feature proposal.md
index ea37cad6f15..dea2384a2e9 100644
--- a/.gitlab/issue_templates/Feature proposal.md
+++ b/.gitlab/issue_templates/Feature proposal.md
@@ -40,12 +40,12 @@ If this feature requires changing permissions, this document https://docs.gitlab
<!-- What risks does this change pose to our availability? How might it affect the quality of the product? What additional test coverage or changes to tests will be needed? Will it require cross-browser testing?
-Please list the test areas (unit, integration and end-to-end) that needs to be added or updated to ensure that this feature will work as intended. Plese use the list below as guidance.
+Please list the test areas (unit, integration and end-to-end) that needs to be added or updated to ensure that this feature will work as intended. Please use the list below as guidance.
* Unit test changes
* Integration test changes
* End-to-end test change
-See the test engineering planning process and reach out to your counterpart Software Engineer in Test for assistance : https://about.gitlab.com/handbook/engineering/quality/test-engineering/#test-planning -->
+See the test engineering planning process and reach out to your counterpart Software Engineer in Test for assistance: https://about.gitlab.com/handbook/engineering/quality/test-engineering/#test-planning -->
### What does success look like, and how can we measure that?
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 02d6b8c8038..a70dc4b79a1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,7 +4,6 @@ entry.
## 12.7.0
-- No changes.
### Security (6 changes, 2 of them are from the community)
- Ensure content matches extension on image uploads. !20697
diff --git a/VERSION b/VERSION
index b654cd4c348..158cd7e61ba 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-12.8.0-pre
+12.7.0-pre
diff --git a/app/assets/javascripts/monitoring/components/charts/time_series.vue b/app/assets/javascripts/monitoring/components/charts/time_series.vue
index 0d442f14aea..8b1a9f6f770 100644
--- a/app/assets/javascripts/monitoring/components/charts/time_series.vue
+++ b/app/assets/javascripts/monitoring/components/charts/time_series.vue
@@ -311,7 +311,10 @@ export default {
<gl-tooltip :target="() => $refs.graphTitle" :disabled="!showTitleTooltip">
{{ graphData.title }}
</gl-tooltip>
- <div class="prometheus-graph-widgets js-graph-widgets flex-fill">
+ <div
+ class="prometheus-graph-widgets js-graph-widgets flex-fill"
+ data-qa-selector="prometheus_graph_widgets"
+ >
<slot></slot>
</div>
</div>
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index 2c51252be39..8c33e13e2f0 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -342,7 +342,7 @@ export default {
</script>
<template>
- <div class="prometheus-graphs">
+ <div class="prometheus-graphs" data-qa-selector="prometheus_graphs">
<div class="prometheus-graphs-header gl-p-3 pb-0 border-bottom bg-gray-light">
<div class="row">
<template v-if="environmentsEndpoint">
diff --git a/app/assets/javascripts/monitoring/components/panel_type.vue b/app/assets/javascripts/monitoring/components/panel_type.vue
index ec6a41d0540..5d4f3425ad0 100644
--- a/app/assets/javascripts/monitoring/components/panel_type.vue
+++ b/app/assets/javascripts/monitoring/components/panel_type.vue
@@ -138,6 +138,7 @@ export default {
v-gl-tooltip
class="ml-auto mx-3"
toggle-class="btn btn-transparent border-0"
+ data-qa-selector="prometheus_widgets_dropdown"
:right="true"
:no-caret="true"
:title="__('More actions')"
@@ -161,7 +162,11 @@ export default {
>
{{ __('Generate link to chart') }}
</gl-dropdown-item>
- <gl-dropdown-item v-if="alertWidgetAvailable" v-gl-modal="`alert-modal-${index}`">
+ <gl-dropdown-item
+ v-if="alertWidgetAvailable"
+ v-gl-modal="`alert-modal-${index}`"
+ data-qa-selector="alert_widget_menu_item"
+ >
{{ __('Alerts') }}
</gl-dropdown-item>
</gl-dropdown>
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index 4195ea6425f..5756532d18d 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -11,7 +11,7 @@ old_notes_spec.js is the spec for the legacy, jQuery notes application. It has n
*/
import $ from 'jquery';
-import _ from 'underscore';
+import { escape, uniqueId } from 'lodash';
import Cookies from 'js-cookie';
import Autosize from 'autosize';
import 'jquery.caret'; // required by at.js
@@ -1449,7 +1449,7 @@ export default class Notes {
return {
// eslint-disable-next-line no-jquery/no-serialize
formData: $form.serialize(),
- formContent: _.escape(content),
+ formContent: escape(content),
formAction: $form.attr('action'),
formContentOriginal: content,
};
@@ -1516,18 +1516,16 @@ export default class Notes {
`<li id="${uniqueId}" class="note being-posted fade-in-half timeline-entry">
<div class="timeline-entry-inner">
<div class="timeline-icon">
- <a href="/${_.escape(currentUsername)}">
+ <a href="/${escape(currentUsername)}">
<img class="avatar s40" src="${currentUserAvatar}" />
</a>
</div>
<div class="timeline-content ${discussionClass}">
<div class="note-header">
<div class="note-header-info">
- <a href="/${_.escape(currentUsername)}">
- <span class="d-none d-sm-inline-block bold">${_.escape(
- currentUsername,
- )}</span>
- <span class="note-headline-light">${_.escape(currentUsername)}</span>
+ <a href="/${escape(currentUsername)}">
+ <span class="d-none d-sm-inline-block bold">${escape(currentUsername)}</span>
+ <span class="note-headline-light">${escape(currentUsername)}</span>
</a>
</div>
</div>
@@ -1541,8 +1539,8 @@ export default class Notes {
</li>`,
);
- $tempNote.find('.d-none.d-sm-inline-block').text(_.escape(currentUserFullname));
- $tempNote.find('.note-headline-light').text(`@${_.escape(currentUsername)}`);
+ $tempNote.find('.d-none.d-sm-inline-block').text(escape(currentUserFullname));
+ $tempNote.find('.note-headline-light').text(`@${escape(currentUsername)}`);
return $tempNote;
}
@@ -1627,7 +1625,7 @@ export default class Notes {
// Show placeholder note
if (tempFormContent) {
- noteUniqueId = _.uniqueId('tempNote_');
+ noteUniqueId = uniqueId('tempNote_');
$notesContainer.append(
this.createPlaceholderNote({
formContent: tempFormContent,
@@ -1642,7 +1640,7 @@ export default class Notes {
// Show placeholder system note
if (hasQuickActions) {
- systemNoteUniqueId = _.uniqueId('tempSystemNote_');
+ systemNoteUniqueId = uniqueId('tempSystemNote_');
$notesContainer.append(
this.createPlaceholderSystemNote({
formContent: this.getQuickActionDescription(
@@ -1825,7 +1823,7 @@ export default class Notes {
})
.catch(() => {
// Submission failed, revert back to original note
- $noteBodyText.html(_.escape(cachedNoteBodyText));
+ $noteBodyText.html(escape(cachedNoteBodyText));
$editingNote.removeClass('being-posted fade-in');
$editingNote.find('.fa.fa-spinner').remove();
diff --git a/app/assets/javascripts/pipelines/components/pipelines_table_row.vue b/app/assets/javascripts/pipelines/components/pipelines_table_row.vue
index afb8439511f..33f5199aabe 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_table_row.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_table_row.vue
@@ -331,6 +331,7 @@ export default {
:loading="isRetrying"
:disabled="isRetrying"
container-class="js-pipelines-retry-button btn btn-default btn-retry"
+ data-qa-selector="pipeline_retry_button"
@click="handleRetryClick"
>
<icon name="repeat" />
diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml
index 3464cc1ea07..d79568d9047 100644
--- a/app/views/layouts/nav/sidebar/_project.html.haml
+++ b/app/views/layouts/nav/sidebar/_project.html.haml
@@ -232,7 +232,7 @@
- if project_nav_tab? :environments
= nav_link(controller: :environments, action: [:metrics, :metrics_redirect]) do
- = link_to metrics_project_environments_path(@project), title: _('Metrics'), class: 'shortcuts-metrics' do
+ = link_to metrics_project_environments_path(@project), title: _('Metrics'), class: 'shortcuts-metrics', data: { qa_selector: 'operations_metrics_link' } do
%span
= _('Metrics')
diff --git a/app/views/shared/_service_settings.html.haml b/app/views/shared/_service_settings.html.haml
index 1bf52feab11..4415c654ab9 100644
--- a/app/views/shared/_service_settings.html.haml
+++ b/app/views/shared/_service_settings.html.haml
@@ -12,7 +12,7 @@
.form-group.row
= form.label :active, "Active", class: "col-form-label col-sm-2"
.col-sm-10
- = form.check_box :active, disabled: disable_fields_service?(@service), data: { qa_selector: 'active_checkbox' }
+ = form.check_box :active, checked: @service.active || @service.new_record?, disabled: disable_fields_service?(@service)
- if @service.configurable_events.present?
.form-group.row
diff --git a/babel.config.js b/babel.config.js
index 91c58cf46bf..ca3baaeee59 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -22,6 +22,7 @@ const plugins = [
'@babel/plugin-proposal-json-strings',
'@babel/plugin-proposal-private-methods',
'@babel/plugin-proposal-optional-chaining',
+ 'lodash',
];
// add code coverage tooling if necessary
diff --git a/changelogs/unreleased/194381-new-integrations-are-not-active-by-default.yml b/changelogs/unreleased/194381-new-integrations-are-not-active-by-default.yml
new file mode 100644
index 00000000000..dcdd46ae92c
--- /dev/null
+++ b/changelogs/unreleased/194381-new-integrations-are-not-active-by-default.yml
@@ -0,0 +1,5 @@
+---
+title: Activate new project integrations by default
+merge_request: 23009
+author:
+type: changed
diff --git a/config/webpack.config.js b/config/webpack.config.js
index 7da7e571d67..639de770fd8 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -92,6 +92,7 @@ const alias = {
vendor: path.join(ROOT_PATH, 'vendor/assets/javascripts'),
vue$: 'vue/dist/vue.esm.js',
spec: path.join(ROOT_PATH, 'spec/javascripts'),
+ jest: path.join(ROOT_PATH, 'spec/frontend'),
// the following resolves files which are different between CE and EE
ee_else_ce: path.join(ROOT_PATH, 'app/assets/javascripts'),
@@ -111,6 +112,7 @@ if (IS_EE) {
ee_icons: path.join(ROOT_PATH, 'ee/app/views/shared/icons'),
ee_images: path.join(ROOT_PATH, 'ee/app/assets/images'),
ee_spec: path.join(ROOT_PATH, 'ee/spec/javascripts'),
+ ee_jest: path.join(ROOT_PATH, 'ee/spec/frontend'),
ee_else_ce: path.join(ROOT_PATH, 'ee/app/assets/javascripts'),
});
}
diff --git a/doc/user/analytics/code_review_analytics.md b/doc/user/analytics/code_review_analytics.md
index 513201e639d..cd2b0dd2bf7 100644
--- a/doc/user/analytics/code_review_analytics.md
+++ b/doc/user/analytics/code_review_analytics.md
@@ -6,23 +6,24 @@ description: "Learn how long your open merge requests have spent in code review,
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/38062) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.7.
-Code Review Analytics can be used to answer questions like:
-
-- How long do open merge requests spend in code review?
-- What distinguishes your longest-running code reviews?
+Code Review Analytics makes it easy to view the longest-running reviews among open merge requests,
+enabling you to take action on individual MRs and reduce overall cycle time.
NOTE: **Note:**
-Initially no data will appear. Data is populated as users comment on open merge requests.
+Initially, no data will appear. Data is populated as users comment on open merge requests.
## Overview
-Code Review Analytics displays a table of open merge requests, which are considered to be in code review.
-Code review starts when a merge request receives its first comment from someone other than the author.
+Code Review Analytics displays a table of open merge requests which are currently considered to be in code review.
+The code review period for an MR is automatically identified as the time since the first non-author comment.
+
+To access Code Review Analytics, from your project's menu, go to **Project Analytics > Code Review**.
-The Code Review Analytics table:
+- The table is sorted by review duration, helping you quickly find the longest-running reviews which may need intervention or to be broken down into smaller parts.
+- You can filter the list of MRs by milestone and label.
+- Columns to display the author, approvers, comment count, and line change (-/+) counts.
-- Is sorted by review time, so the longest reviews appear at the top.
-- Has columns to display the author, approvers, comment count, and line -/+ counts.
+## Use cases
This feature is designed for [development team leaders](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#delaney-development-team-lead)
and others who want to understand broad code review dynamics, and identify patterns to help explain them.
@@ -30,14 +31,12 @@ and others who want to understand broad code review dynamics, and identify patte
You can use Code Review Analytics to expose your team's unique challenges with code review, and
identify improvements that might substantially accelerate your development cycle.
-## Use cases
-
Code Review Analytics can be used when:
- Your team agrees that code review is moving too slow.
- The [Cycle Analytics feature](cycle_analytics.md) shows that reviews are your team's most time-consuming step.
-You can use Code Review Analytics to see what is currently moving slowest, and analyze the patterns
+You can use Code Review Analytics to see the types of work that are currently moving the slowest, and analyze the patterns
and trends between them. For example:
- Lots of comments or commits? Maybe the code is too complex.
diff --git a/jest.config.js b/jest.config.js
index 59e09c85b5a..d07c034e88e 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -38,6 +38,7 @@ const moduleNameMapper = {
'\\.(jpg|jpeg|png|svg)$': '<rootDir>/spec/frontend/__mocks__/file_mock.js',
'emojis(/.*).json': '<rootDir>/fixtures/emojis$1.json',
'^spec/test_constants$': '<rootDir>/spec/frontend/helpers/test_constants',
+ '^jest/(.*)$': '<rootDir>/spec/frontend/$1',
};
const collectCoverageFrom = ['<rootDir>/app/assets/javascripts/**/*.{js,vue}'];
@@ -48,6 +49,7 @@ if (IS_EE) {
'^ee(/.*)$': rootDirEE,
'^ee_component(/.*)$': rootDirEE,
'^ee_else_ce(/.*)$': rootDirEE,
+ '^ee_jest/(.*)$': '<rootDir>/ee/spec/frontend/$1',
});
collectCoverageFrom.push(rootDirEE.replace('$1', '/**/*.{js,vue}'));
diff --git a/package.json b/package.json
index df3c28ada2a..9a3553dcce3 100644
--- a/package.json
+++ b/package.json
@@ -54,6 +54,7 @@
"aws-sdk": "^2.526.0",
"axios": "^0.19.0",
"babel-loader": "^8.0.6",
+ "babel-plugin-lodash": "^3.3.4",
"bootstrap": "4.3.1",
"brace-expansion": "^1.1.8",
"cache-loader": "^4.1.0",
@@ -94,6 +95,7 @@
"jszip": "^3.1.3",
"jszip-utils": "^0.0.2",
"katex": "^0.10.0",
+ "lodash": "^4.17.15",
"marked": "^0.3.12",
"mermaid": "^8.4.5",
"monaco-editor": "^0.18.1",
diff --git a/qa/qa.rb b/qa/qa.rb
index a0ce6caa3a9..53e119b5ced 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -289,6 +289,8 @@ module QA
autoload :AddExisting, 'qa/page/project/operations/kubernetes/add_existing'
autoload :Show, 'qa/page/project/operations/kubernetes/show'
end
+
+ autoload :Metrics, 'qa/page/project/operations/metrics'
end
module Wiki
diff --git a/qa/qa/fixtures/monitored_auto_devops/.gitlab-ci.yml b/qa/qa/fixtures/monitored_auto_devops/.gitlab-ci.yml
new file mode 100644
index 00000000000..a65ae5aa1d9
--- /dev/null
+++ b/qa/qa/fixtures/monitored_auto_devops/.gitlab-ci.yml
@@ -0,0 +1,337 @@
+# This is stripped down version of the .gitlab-ci.yml found
+# here: https://gitlab.com/joshlambert/autodevops-deploy.
+#
+# It performs only the deploy stage.
+
+image: alpine:latest
+
+variables:
+ # AUTO_DEVOPS_DOMAIN is the application deployment domain and should be set as a variable at the group or project level.
+ AUTO_DEVOPS_DOMAIN: my-fake-domain.com
+
+ POSTGRES_USER: user
+ POSTGRES_PASSWORD: testing-password
+ POSTGRES_ENABLED: 'false'
+ POSTGRES_DB: $CI_ENVIRONMENT_SLUG
+
+ KUBERNETES_VERSION: 1.11.6
+ HELM_VERSION: 2.12.2
+
+ DOCKER_DRIVER: overlay2
+
+stages:
+ - production
+
+# This job continuously deploys to production on every push to `master`.
+
+production:
+ stage: production
+ script:
+ - check_kube_domain
+ - install_dependencies
+ - download_chart
+ - ensure_namespace
+ - initialize_tiller
+ - create_secret
+ - deploy
+ - persist_environment_url
+ environment:
+ name: production
+ url: http://$CI_PROJECT_PATH_SLUG.$AUTO_DEVOPS_DOMAIN
+ artifacts:
+ paths: [environment_url.txt]
+ only:
+ refs:
+ - master
+ kubernetes: active
+
+# ---------------------------------------------------------------------------
+
+.auto_devops: &auto_devops |
+ # Auto DevOps variables and functions
+ [[ "$TRACE" ]] && set -x
+ auto_database_url=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${CI_ENVIRONMENT_SLUG}-postgres:5432/${POSTGRES_DB}
+ export DATABASE_URL=${DATABASE_URL-$auto_database_url}
+ export CI_APPLICATION_REPOSITORY=$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG
+ export CI_APPLICATION_TAG=$CI_COMMIT_SHA
+ export CI_CONTAINER_NAME=ci_job_build_${CI_JOB_ID}
+ export TILLER_NAMESPACE=$KUBE_NAMESPACE
+ # Extract "MAJOR.MINOR" from CI_SERVER_VERSION and generate "MAJOR-MINOR-stable" for Security Products
+ export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
+
+
+ function get_replicas() {
+ track="${1:-stable}"
+ percentage="${2:-100}"
+
+ env_track=$( echo $track | tr -s '[:lower:]' '[:upper:]' )
+ env_slug=$( echo ${CI_ENVIRONMENT_SLUG//-/_} | tr -s '[:lower:]' '[:upper:]' )
+
+ if [[ "$track" == "stable" ]] || [[ "$track" == "rollout" ]]; then
+ # for stable track get number of replicas from `PRODUCTION_REPLICAS`
+ eval new_replicas=\$${env_slug}_REPLICAS
+ if [[ -z "$new_replicas" ]]; then
+ new_replicas=$REPLICAS
+ fi
+ else
+ # for all tracks get number of replicas from `CANARY_PRODUCTION_REPLICAS`
+ eval new_replicas=\$${env_track}_${env_slug}_REPLICAS
+ if [[ -z "$new_replicas" ]]; then
+ eval new_replicas=\${env_track}_REPLICAS
+ fi
+ fi
+
+ replicas="${new_replicas:-1}"
+ replicas="$(($replicas * $percentage / 100))"
+
+ # always return at least one replicas
+ if [[ $replicas -gt 0 ]]; then
+ echo "$replicas"
+ else
+ echo 1
+ fi
+ }
+
+
+ # Extracts variables prefixed with K8S_SECRET_
+ # and creates a Kubernetes secret.
+ #
+ # e.g. If we have the following environment variables:
+ # K8S_SECRET_A=value1
+ # K8S_SECRET_B=multi\ word\ value
+ #
+ # Then we will create a secret with the following key-value pairs:
+ # data:
+ # A: dmFsdWUxCg==
+ # B: bXVsdGkgd29yZCB2YWx1ZQo=
+ function create_application_secret() {
+ track="${1-stable}"
+ export APPLICATION_SECRET_NAME=$(application_secret_name "$track")
+
+ env | sed -n "s/^K8S_SECRET_\(.*\)$/\1/p" > k8s_prefixed_variables
+
+ kubectl create secret \
+ -n "$KUBE_NAMESPACE" generic "$APPLICATION_SECRET_NAME" \
+ --from-env-file k8s_prefixed_variables -o yaml --dry-run |
+ kubectl replace -n "$KUBE_NAMESPACE" --force -f -
+
+ export APPLICATION_SECRET_CHECKSUM=$(cat k8s_prefixed_variables | sha256sum | cut -d ' ' -f 1)
+
+ rm k8s_prefixed_variables
+ }
+
+ function deploy_name() {
+ name="$CI_ENVIRONMENT_SLUG"
+ track="${1-stable}"
+
+ if [[ "$track" != "stable" ]]; then
+ name="$name-$track"
+ fi
+
+ echo $name
+ }
+
+ function application_secret_name() {
+ track="${1-stable}"
+ name=$(deploy_name "$track")
+
+ echo "${name}-secret"
+ }
+
+
+ function deploy() {
+ track="${1-stable}"
+ percentage="${2:-100}"
+ name=$(deploy_name "$track")
+
+ replicas="1"
+ service_enabled="true"
+ postgres_enabled="$POSTGRES_ENABLED"
+
+ # if track is different than stable,
+ # re-use all attached resources
+ if [[ "$track" != "stable" ]]; then
+ service_enabled="false"
+ postgres_enabled="false"
+ fi
+
+ replicas=$(get_replicas "$track" "$percentage")
+
+ if [[ "$CI_PROJECT_VISIBILITY" != "public" ]]; then
+ secret_name='gitlab-registry'
+ else
+ secret_name=''
+ fi
+
+ create_application_secret "$track"
+
+ env_slug=$(echo ${CI_ENVIRONMENT_SLUG//-/_} | tr -s '[:lower:]' '[:upper:]')
+ eval env_ADDITIONAL_HOSTS=\$${env_slug}_ADDITIONAL_HOSTS
+ if [ -n "$env_ADDITIONAL_HOSTS" ]; then
+ additional_hosts="{$env_ADDITIONAL_HOSTS}"
+ elif [ -n "$ADDITIONAL_HOSTS" ]; then
+ additional_hosts="{$ADDITIONAL_HOSTS}"
+ fi
+
+ if [[ -n "$DB_INITIALIZE" && -z "$(helm ls -q "^$name$")" ]]; then
+ echo "Deploying first release with database initialization..."
+ helm upgrade --install \
+ --wait \
+ --set service.enabled="$service_enabled" \
+ --set releaseOverride="$CI_ENVIRONMENT_SLUG" \
+ --set image.repository="registry.gitlab.com/joshlambert/ruby-gke/master" \
+ --set image.tag="63492726c2264a0277141d6a6573c3d22ecd7de3" \
+ --set image.pullPolicy=IfNotPresent \
+ --set image.secrets[0].name="$secret_name" \
+ --set application.track="$track" \
+ --set application.database_url="$DATABASE_URL" \
+ --set application.secretName="$APPLICATION_SECRET_NAME" \
+ --set application.secretChecksum="$APPLICATION_SECRET_CHECKSUM" \
+ --set service.url="$CI_ENVIRONMENT_URL" \
+ --set service.additionalHosts="$additional_hosts" \
+ --set replicaCount="$replicas" \
+ --set postgresql.enabled="$postgres_enabled" \
+ --set postgresql.nameOverride="postgres" \
+ --set postgresql.postgresUser="$POSTGRES_USER" \
+ --set postgresql.postgresPassword="$POSTGRES_PASSWORD" \
+ --set postgresql.postgresDatabase="$POSTGRES_DB" \
+ --set application.initializeCommand="$DB_INITIALIZE" \
+ --set gitlab.app="$CI_PROJECT_PATH_SLUG" \
+ --set gitlab.env="$CI_ENVIRONMENT_SLUG" \
+ --namespace="$KUBE_NAMESPACE" \
+ "$name" \
+ chart/
+
+ echo "Deploying second release..."
+ helm upgrade --reuse-values \
+ --wait \
+ --set application.initializeCommand="" \
+ --set application.migrateCommand="$DB_MIGRATE" \
+ --namespace="$KUBE_NAMESPACE" \
+ "$name" \
+ chart/
+ else
+ echo "Deploying new release..."
+ helm upgrade --install \
+ --wait \
+ --set service.enabled="$service_enabled" \
+ --set releaseOverride="$CI_ENVIRONMENT_SLUG" \
+ --set image.repository="registry.gitlab.com/joshlambert/ruby-gke/master" \
+ --set image.tag="63492726c2264a0277141d6a6573c3d22ecd7de3" \
+ --set image.pullPolicy=IfNotPresent \
+ --set image.secrets[0].name="$secret_name" \
+ --set application.track="$track" \
+ --set application.database_url="$DATABASE_URL" \
+ --set application.secretName="$APPLICATION_SECRET_NAME" \
+ --set application.secretChecksum="$APPLICATION_SECRET_CHECKSUM" \
+ --set service.url="$CI_ENVIRONMENT_URL" \
+ --set service.additionalHosts="$additional_hosts" \
+ --set replicaCount="$replicas" \
+ --set postgresql.enabled="$postgres_enabled" \
+ --set postgresql.nameOverride="postgres" \
+ --set postgresql.postgresUser="$POSTGRES_USER" \
+ --set postgresql.postgresPassword="$POSTGRES_PASSWORD" \
+ --set postgresql.postgresDatabase="$POSTGRES_DB" \
+ --set application.migrateCommand="$DB_MIGRATE" \
+ --set gitlab.app="$CI_PROJECT_PATH_SLUG" \
+ --set gitlab.env="$CI_ENVIRONMENT_SLUG" \
+ --namespace="$KUBE_NAMESPACE" \
+ "$name" \
+ chart/
+ fi
+
+ kubectl rollout status -n "$KUBE_NAMESPACE" -w "deployment/$name"
+ }
+
+
+ function install_dependencies() {
+ apk add -U openssl curl tar gzip bash ca-certificates git
+ wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub
+ wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.23-r3/glibc-2.23-r3.apk
+ apk add glibc-2.23-r3.apk
+ rm glibc-2.23-r3.apk
+
+ curl "https://kubernetes-helm.storage.googleapis.com/helm-v${HELM_VERSION}-linux-amd64.tar.gz" | tar zx
+ mv linux-amd64/helm /usr/bin/
+ mv linux-amd64/tiller /usr/bin/
+ helm version --client
+ tiller -version
+
+ curl -L -o /usr/bin/kubectl "https://storage.googleapis.com/kubernetes-release/release/v${KUBERNETES_VERSION}/bin/linux/amd64/kubectl"
+ chmod +x /usr/bin/kubectl
+ kubectl version --client
+ }
+
+ function download_chart() {
+ if [[ ! -d chart ]]; then
+ auto_chart=${AUTO_DEVOPS_CHART:-gitlab/auto-deploy-app}
+ auto_chart_name=$(basename $auto_chart)
+ auto_chart_name=${auto_chart_name%.tgz}
+ else
+ auto_chart="chart"
+ auto_chart_name="chart"
+ fi
+
+ helm init --client-only
+ helm repo add gitlab https://charts.gitlab.io
+ if [[ ! -d "$auto_chart" ]]; then
+ helm fetch ${auto_chart} --untar
+ fi
+ if [ "$auto_chart_name" != "chart" ]; then
+ mv ${auto_chart_name} chart
+ fi
+
+ helm dependency update chart/
+ helm dependency build chart/
+ }
+
+ function ensure_namespace() {
+ kubectl describe namespace "$KUBE_NAMESPACE" || kubectl create namespace "$KUBE_NAMESPACE"
+ }
+
+ function check_kube_domain() {
+ if [ -z ${AUTO_DEVOPS_DOMAIN+x} ]; then
+ echo "In order to deploy or use Review Apps, AUTO_DEVOPS_DOMAIN variable must be set"
+ echo "You can do it in Auto DevOps project settings or defining a secret variable at group or project level"
+ echo "You can also manually add it in .gitlab-ci.yml"
+ false
+ else
+ true
+ fi
+ }
+
+ function initialize_tiller() {
+ echo "Checking Tiller..."
+
+ export HELM_HOST="localhost:44134"
+ tiller -listen ${HELM_HOST} -alsologtostderr > /dev/null 2>&1 &
+ echo "Tiller is listening on ${HELM_HOST}"
+
+ if ! helm version --debug; then
+ echo "Failed to init Tiller."
+ return 1
+ fi
+ echo ""
+ }
+
+ function create_secret() {
+ echo "Create secret..."
+ if [[ "$CI_PROJECT_VISIBILITY" == "public" ]]; then
+ return
+ fi
+
+ kubectl create secret -n "$KUBE_NAMESPACE" \
+ docker-registry gitlab-registry \
+ --docker-server="$CI_REGISTRY" \
+ --docker-username="$CI_REGISTRY_USER" \
+ --docker-password="$CI_REGISTRY_PASSWORD" \
+ --docker-email="$GITLAB_USER_EMAIL" \
+ -o yaml --dry-run | kubectl replace -n "$KUBE_NAMESPACE" --force -f -
+ }
+
+ function persist_environment_url() {
+ echo $CI_ENVIRONMENT_URL > environment_url.txt
+ }
+
+before_script:
+ - *auto_devops
diff --git a/qa/qa/page/layout/performance_bar.rb b/qa/qa/page/layout/performance_bar.rb
index 4e144e67f12..c593783a730 100644
--- a/qa/qa/page/layout/performance_bar.rb
+++ b/qa/qa/page/layout/performance_bar.rb
@@ -21,9 +21,9 @@ module QA
has_element?(:performance_bar)
end
- def has_detailed_metrics?(count)
+ def has_detailed_metrics?(minimum_count)
retry_until(sleep_interval: 1) do
- all_elements(:detailed_metric_content, count: count).all? do |metric|
+ all_elements(:detailed_metric_content, minimum: minimum_count).all? do |metric|
metric.has_text?(%r{\d+})
end
end
diff --git a/qa/qa/page/project/operations/metrics.rb b/qa/qa/page/project/operations/metrics.rb
new file mode 100644
index 00000000000..cf5578ef26b
--- /dev/null
+++ b/qa/qa/page/project/operations/metrics.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module Operations
+ class Metrics < Page::Base
+ EXPECTED_TITLE = 'Memory Usage (Total)'
+ EXPECTED_LABEL = 'Total (GB)'
+ LOADING_MESSAGE = 'Waiting for performance data'
+
+ view 'app/assets/javascripts/monitoring/components/dashboard.vue' do
+ element :prometheus_graphs
+ end
+
+ view 'app/assets/javascripts/monitoring/components/charts/time_series.vue' do
+ element :prometheus_graph_widgets
+ end
+
+ view 'app/assets/javascripts/monitoring/components/panel_type.vue' do
+ element :prometheus_widgets_dropdown
+ element :alert_widget_menu_item
+ end
+
+ view 'ee/app/assets/javascripts/monitoring/components/alert_widget_form.vue' do
+ element :alert_query_dropdown
+ element :alert_query_option
+ element :alert_threshold_field
+ end
+
+ def wait_for_metrics
+ wait_for_data
+ return if has_metrics?
+
+ wait_until(max_duration: 180) do
+ wait_for_data
+ has_metrics?
+ end
+ end
+
+ def wait_for_data
+ wait_until(reload: false) { !has_text?(LOADING_MESSAGE) } if has_text?(LOADING_MESSAGE)
+ end
+
+ def has_metrics?
+ within_element :prometheus_graphs do
+ has_text?(EXPECTED_TITLE)
+ end
+ end
+
+ def wait_for_alert(operator = '>', threshold = 0)
+ wait_until(reload: false) { has_alert?(operator, threshold) }
+ end
+
+ def has_alert?(operator = '>', threshold = 0)
+ within_element :prometheus_graphs do
+ has_text?([EXPECTED_LABEL, operator, threshold].join(' '))
+ end
+ end
+
+ def write_first_alert(operator = '>', threshold = 0)
+ open_first_alert_modal
+ click_on operator
+ fill_element :alert_threshold_field, threshold
+
+ within('.modal-content') { click_button(class: 'btn-success') }
+ end
+
+ def delete_first_alert
+ open_first_alert_modal
+
+ within('.modal-content') { click_button(class: 'btn-danger') }
+ wait_for_requests
+ end
+
+ def open_first_alert_modal
+ all_elements(:prometheus_widgets_dropdown, minimum: 1).first.click
+ click_element :alert_widget_menu_item
+
+ click_element :alert_query_dropdown unless has_element?(:alert_query_option, wait: 3)
+ all_elements(:alert_query_option, minimum: 1).first.click
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/pipeline/index.rb b/qa/qa/page/project/pipeline/index.rb
index 684ad4a59d5..f018e4bf018 100644
--- a/qa/qa/page/project/pipeline/index.rb
+++ b/qa/qa/page/project/pipeline/index.rb
@@ -9,6 +9,7 @@ module QA::Page
view 'app/assets/javascripts/pipelines/components/pipelines_table_row.vue' do
element :pipeline_commit_status
+ element :pipeline_retry_button
end
def click_on_latest_pipeline
@@ -18,10 +19,25 @@ module QA::Page
end
def wait_for_latest_pipeline_success
+ wait_for_latest_pipeline_status { has_text?('passed') }
+ end
+
+ def wait_for_latest_pipeline_completion
+ wait_for_latest_pipeline_status { has_text?('passed') || has_text?('failed') }
+ end
+
+ def wait_for_latest_pipeline_status
wait_until(reload: false, max_duration: 300) do
- within_element_by_index(:pipeline_commit_status, 0) do
- has_text?('passed')
- end
+ within_element_by_index(:pipeline_commit_status, 0) { yield }
+ end
+ end
+
+ def wait_for_latest_pipeline_success_or_retry
+ wait_for_latest_pipeline_completion
+
+ if has_text?('failed')
+ click_element :pipeline_retry_button
+ wait_for_latest_pipeline_success
end
end
end
diff --git a/qa/qa/page/project/sub_menus/operations.rb b/qa/qa/page/project/sub_menus/operations.rb
index d266cb21417..bcbc1dc16d3 100644
--- a/qa/qa/page/project/sub_menus/operations.rb
+++ b/qa/qa/page/project/sub_menus/operations.rb
@@ -12,6 +12,7 @@ module QA
view 'app/views/layouts/nav/sidebar/_project.html.haml' do
element :link_operations
element :operations_environments_link
+ element :operations_metrics_link
end
end
end
@@ -24,6 +25,14 @@ module QA
end
end
+ def go_to_operations_metrics
+ hover_operations do
+ within_submenu do
+ click_element(:operations_metrics_link)
+ end
+ end
+ end
+
def go_to_operations_kubernetes
hover_operations do
within_submenu do
diff --git a/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb b/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb
index 4a5bb077e69..c6d5fba919b 100644
--- a/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb
+++ b/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb
@@ -4,8 +4,8 @@ module QA
context 'Non-devops' do
describe 'Performance bar display', :requires_admin do
context 'when logged in as an admin user' do
- # 4 metrics: pg, gitaly, redis, total
- let(:metrics_count) { 4 }
+ # performance metrics: pg, gitaly, redis, rugged (feature flagged), total (not always provided)
+ let(:minimum_metrics_count) { 3 }
before do
Flow::Login.sign_in_as_admin
@@ -28,7 +28,7 @@ module QA
Page::Layout::PerformanceBar.perform do |bar_component|
expect(bar_component).to have_performance_bar
- expect(bar_component).to have_detailed_metrics(metrics_count)
+ expect(bar_component).to have_detailed_metrics(minimum_metrics_count)
expect(bar_component).to have_request_for('realtime_changes') # Always requested on issue pages
end
end
diff --git a/spec/features/projects/services/user_activates_issue_tracker_spec.rb b/spec/features/projects/services/user_activates_issue_tracker_spec.rb
index 5f3bb794b48..0b0a3362043 100644
--- a/spec/features/projects/services/user_activates_issue_tracker_spec.rb
+++ b/spec/features/projects/services/user_activates_issue_tracker_spec.rb
@@ -8,16 +8,15 @@ describe 'User activates issue tracker', :js do
let(:url) { 'http://tracker.example.com' }
- def fill_short_form(active = true)
- check 'Active' if active
+ def fill_short_form(disabled: false)
+ uncheck 'Active' if disabled
fill_in 'service_project_url', with: url
fill_in 'service_issues_url', with: "#{url}/:id"
end
- def fill_full_form(active = true)
- fill_short_form(active)
- check 'Active' if active
+ def fill_full_form(disabled: false)
+ fill_short_form(disabled: disabled)
fill_in 'service_new_issue_url', with: url
end
@@ -86,14 +85,14 @@ describe 'User activates issue tracker', :js do
end
end
- describe 'user sets the service but keeps it disabled' do
+ describe 'user disables the service' do
before do
click_link(tracker)
if skip_new_issue_url
- fill_short_form(false)
+ fill_short_form(disabled: true)
else
- fill_full_form(false)
+ fill_full_form(disabled: true)
end
click_button('Save changes')
diff --git a/spec/features/projects/services/user_activates_jira_spec.rb b/spec/features/projects/services/user_activates_jira_spec.rb
index 7847b7d5177..557615f8872 100644
--- a/spec/features/projects/services/user_activates_jira_spec.rb
+++ b/spec/features/projects/services/user_activates_jira_spec.rb
@@ -9,8 +9,8 @@ describe 'User activates Jira', :js do
let(:url) { 'http://jira.example.com' }
let(:test_url) { 'http://jira.example.com/rest/api/2/serverInfo' }
- def fill_form(active = true)
- check 'Active' if active
+ def fill_form(disabled: false)
+ uncheck 'Active' if disabled
fill_in 'service_url', with: url
fill_in 'service_username', with: 'username'
@@ -83,10 +83,10 @@ describe 'User activates Jira', :js do
end
end
- describe 'user sets Jira Service but keeps it disabled' do
+ describe 'user disables the Jira Service' do
before do
click_link('Jira')
- fill_form(false)
+ fill_form(disabled: true)
click_button('Save changes')
end
diff --git a/spec/features/projects/services/user_activates_youtrack_spec.rb b/spec/features/projects/services/user_activates_youtrack_spec.rb
index 8fdeddfdfb4..2f6aad1d736 100644
--- a/spec/features/projects/services/user_activates_youtrack_spec.rb
+++ b/spec/features/projects/services/user_activates_youtrack_spec.rb
@@ -8,8 +8,8 @@ describe 'User activates issue tracker', :js do
let(:url) { 'http://tracker.example.com' }
- def fill_form(active = true)
- check 'Active' if active
+ def fill_form(disabled: false)
+ uncheck 'Active' if disabled
fill_in 'service_project_url', with: url
fill_in 'service_issues_url', with: "#{url}/:id"
@@ -67,10 +67,10 @@ describe 'User activates issue tracker', :js do
end
end
- describe 'user sets the service but keeps it disabled' do
+ describe 'user disables the service' do
before do
click_link(tracker)
- fill_form(false)
+ fill_form(disabled: true)
click_button('Save changes')
end
diff --git a/spec/features/projects/tree/create_directory_spec.rb b/spec/features/projects/tree/create_directory_spec.rb
index 7e0ee861b18..829b01832df 100644
--- a/spec/features/projects/tree/create_directory_spec.rb
+++ b/spec/features/projects/tree/create_directory_spec.rb
@@ -46,6 +46,13 @@ describe 'Multi-file editor new directory', :js do
find('.js-ide-commit-mode').click
+ # Compact mode depends on the size of window. If it is shorter than MAX_WINDOW_HEIGHT_COMPACT,
+ # (as it is with CHROME_HEADLESS=0), this initial commit button will exist. Otherwise, if it is
+ # taller (as it is by default with chrome headless) then the button will not exist.
+ if page.has_css?('.qa-begin-commit-button')
+ find('.qa-begin-commit-button').click
+ end
+
fill_in('commit-message', with: 'commit message ide')
find(:css, ".js-ide-commit-new-mr input").set(false)
diff --git a/spec/features/projects/tree/create_file_spec.rb b/spec/features/projects/tree/create_file_spec.rb
index eba33168006..58ff623c9ae 100644
--- a/spec/features/projects/tree/create_file_spec.rb
+++ b/spec/features/projects/tree/create_file_spec.rb
@@ -36,6 +36,13 @@ describe 'Multi-file editor new file', :js do
find('.js-ide-commit-mode').click
+ # Compact mode depends on the size of window. If it is shorter than MAX_WINDOW_HEIGHT_COMPACT,
+ # (as it is with CHROME_HEADLESS=0), this initial commit button will exist. Otherwise, if it is
+ # taller (as it is by default with chrome headless) then the button will not exist.
+ if page.has_css?('.qa-begin-commit-button')
+ find('.qa-begin-commit-button').click
+ end
+
fill_in('commit-message', with: 'commit message ide')
find(:css, ".js-ide-commit-new-mr input").set(false)
diff --git a/spec/frontend/boards/issue_card_spec.js b/spec/frontend/boards/issue_card_spec.js
index df55a106945..08cffed5f00 100644
--- a/spec/frontend/boards/issue_card_spec.js
+++ b/spec/frontend/boards/issue_card_spec.js
@@ -1,6 +1,6 @@
/* global ListAssignee, ListLabel, ListIssue */
import { mount } from '@vue/test-utils';
-import _ from 'underscore';
+import { range } from 'lodash';
import '~/boards/models/label';
import '~/boards/models/assignee';
import '~/boards/models/issue';
@@ -222,7 +222,7 @@ describe('Issue card component', () => {
it('renders 99+ avatar counter', done => {
const assignees = [
...wrapper.props('issue').assignees,
- ..._.range(5, 103).map(
+ ...range(5, 103).map(
i =>
new ListAssignee({
id: i,
diff --git a/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js b/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js
index 3ce105f27e4..d924f895da8 100644
--- a/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js
+++ b/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js
@@ -1,4 +1,4 @@
-import _ from 'underscore';
+import { pick, clone } from 'lodash';
import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
@@ -15,7 +15,7 @@ describe('error tracking settings project dropdown', () => {
wrapper = shallowMount(ProjectDropdown, {
localVue,
propsData: {
- ..._.pick(
+ ...pick(
defaultProps,
'dropdownLabel',
'invalidProjectLabel',
@@ -65,7 +65,7 @@ describe('error tracking settings project dropdown', () => {
describe('populated project list', () => {
beforeEach(() => {
- wrapper.setProps({ projects: _.clone(projectList), hasProjects: true });
+ wrapper.setProps({ projects: clone(projectList), hasProjects: true });
return wrapper.vm.$nextTick();
});
@@ -82,10 +82,10 @@ describe('error tracking settings project dropdown', () => {
});
describe('selected project', () => {
- const selectedProject = _.clone(projectList[0]);
+ const selectedProject = clone(projectList[0]);
beforeEach(() => {
- wrapper.setProps({ projects: _.clone(projectList), selectedProject, hasProjects: true });
+ wrapper.setProps({ projects: clone(projectList), selectedProject, hasProjects: true });
return wrapper.vm.$nextTick();
});
@@ -98,7 +98,7 @@ describe('error tracking settings project dropdown', () => {
describe('invalid project selected', () => {
beforeEach(() => {
wrapper.setProps({
- projects: _.clone(projectList),
+ projects: clone(projectList),
selectedProject: staleProject,
isProjectInvalid: true,
});
diff --git a/spec/frontend/notes/old_notes_spec.js b/spec/frontend/notes/old_notes_spec.js
index c1c9d5cef4a..5f7a5d57cd8 100644
--- a/spec/frontend/notes/old_notes_spec.js
+++ b/spec/frontend/notes/old_notes_spec.js
@@ -1,7 +1,6 @@
/* eslint-disable import/no-commonjs, no-new */
import $ from 'jquery';
-import _ from 'underscore';
import MockAdapter from 'axios-mock-adapter';
import '~/behaviors/markdown/render_gfm';
import { createSpyObj } from 'helpers/jest_helpers';
@@ -792,14 +791,11 @@ describe('Old Notes (~/notes.js)', () => {
});
it('should return form metadata with sanitized formContent from form reference', () => {
- jest.spyOn(_, 'escape');
-
sampleComment = '<script>alert("Boom!");</script>';
$form.find('textarea.js-note-text').val(sampleComment);
const { formContent } = notes.getFormData($form);
- expect(_.escape).toHaveBeenCalledWith(sampleComment);
expect(formContent).toEqual('&lt;script&gt;alert(&quot;Boom!&quot;);&lt;/script&gt;');
});
});
@@ -990,7 +986,6 @@ describe('Old Notes (~/notes.js)', () => {
beforeEach(() => {
notes = new Notes('', []);
- jest.spyOn(_, 'escape');
});
it('should return constructed placeholder element for system note based on form contents', () => {
diff --git a/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js b/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js
index 2f68e15b0d7..902e83da7be 100644
--- a/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js
+++ b/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js
@@ -1,4 +1,4 @@
-import _ from 'underscore';
+import { each } from 'lodash';
import { trimText } from 'helpers/text_helper';
import { shallowMount } from '@vue/test-utils';
import { GlLink } from '@gitlab/ui';
@@ -58,7 +58,7 @@ describe('User Avatar Link Component', () => {
});
it('should return necessary props as defined', () => {
- _.each(defaultProps, (val, key) => {
+ each(defaultProps, (val, key) => {
expect(wrapper.vm[key]).toBeDefined();
});
});
diff --git a/yarn.lock b/yarn.lock
index a4c4890fc4f..a3c8f4b2297 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -122,12 +122,12 @@
dependencies:
"@babel/types" "^7.5.5"
-"@babel/helper-module-imports@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d"
- integrity sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==
+"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.0.0-beta.49":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498"
+ integrity sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==
dependencies:
- "@babel/types" "^7.0.0"
+ "@babel/types" "^7.8.3"
"@babel/helper-module-transforms@^7.1.0", "@babel/helper-module-transforms@^7.4.4":
version "7.5.5"
@@ -683,10 +683,10 @@
globals "^11.1.0"
lodash "^4.17.13"
-"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5", "@babel/types@^7.6.0":
- version "7.6.1"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.1.tgz#53abf3308add3ac2a2884d539151c57c4b3ac648"
- integrity sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==
+"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5", "@babel/types@^7.6.0", "@babel/types@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c"
+ integrity sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==
dependencies:
esutils "^2.0.2"
lodash "^4.17.13"
@@ -1890,6 +1890,17 @@ babel-plugin-jest-hoist@^24.6.0:
dependencies:
"@types/babel__traverse" "^7.0.6"
+babel-plugin-lodash@^3.3.4:
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/babel-plugin-lodash/-/babel-plugin-lodash-3.3.4.tgz#4f6844358a1340baed182adbeffa8df9967bc196"
+ integrity sha512-yDZLjK7TCkWl1gpBeBGmuaDIFhZKmkoL+Cu2MUUjv5VxUZx/z7tBGBCBcQs5RI1Bkz5LLmNdjx7paOyQtMovyg==
+ dependencies:
+ "@babel/helper-module-imports" "^7.0.0-beta.49"
+ "@babel/types" "^7.0.0-beta.49"
+ glob "^7.1.1"
+ lodash "^4.17.10"
+ require-package-name "^2.0.1"
+
babel-plugin-rewire@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/babel-plugin-rewire/-/babel-plugin-rewire-1.2.0.tgz#822562d72ed2c84e47c0f95ee232c920853e9d89"
@@ -9725,6 +9736,11 @@ require-main-filename@^2.0.0:
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
+require-package-name@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/require-package-name/-/require-package-name-2.0.1.tgz#c11e97276b65b8e2923f75dabf5fb2ef0c3841b9"
+ integrity sha1-wR6XJ2tluOKSP3Xav1+y7ww4Qbk=
+
require-uncached@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"