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:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-05-08 12:09:39 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-05-08 12:09:39 +0300
commit5bdbc604c8a08f827c3833e2c28ec0c299bb41fc (patch)
tree1fbf5e5dc3bff54d371baa15775371ebc8525f62
parent79ddf163588de2d9a7f1cc27262dc1a14503f619 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/design_management/pages/design/index.vue14
-rw-r--r--app/assets/javascripts/design_management/utils/tracking.js22
-rw-r--r--app/controllers/projects/issues_controller.rb4
-rw-r--r--app/helpers/projects/alert_management_helper.rb2
-rw-r--r--app/models/project.rb18
-rw-r--r--app/presenters/projects/prometheus/alert_presenter.rb61
-rw-r--r--app/services/issues/build_service.rb10
-rw-r--r--changelogs/unreleased/216472-move-embeding-metrics-to-core.yml5
-rw-r--r--changelogs/unreleased/add_confidential_issue_url_param.yml5
-rw-r--r--doc/.vale/gitlab/BadgeCapitalization.yml42
-rw-r--r--doc/user/application_security/dast/index.md2
-rw-r--r--doc/user/group/epics/img/epic_view_v12.3.pngbin61402 -> 0 bytes
-rw-r--r--doc/user/group/epics/img/epic_view_v13.0.pngbin0 -> 68803 bytes
-rw-r--r--doc/user/group/epics/index.md6
-rw-r--r--doc/user/project/issues/managing_issues.md16
-rw-r--r--lib/gitlab/prometheus_client.rb2
-rw-r--r--lib/mattermost/client.rb2
-rw-r--r--locale/gitlab.pot21
-rw-r--r--scripts/rspec_helpers.sh6
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb27
-rw-r--r--spec/frontend/design_management/router_spec.js79
-rw-r--r--spec/frontend/design_management/utils/tracking_spec.js51
-rw-r--r--spec/frontend/diffs/components/diff_content_spec.js2
-rw-r--r--spec/frontend/notebook/cells/code_spec.js (renamed from spec/javascripts/notebook/cells/code_spec.js)6
-rw-r--r--spec/frontend/notebook/cells/markdown_spec.js (renamed from spec/javascripts/notebook/cells/markdown_spec.js)2
-rw-r--r--spec/frontend/notebook/cells/output/html_sanitize_tests.js (renamed from spec/javascripts/notebook/cells/output/html_sanitize_tests.js)0
-rw-r--r--spec/frontend/notebook/cells/output/html_spec.js (renamed from spec/javascripts/notebook/cells/output/html_spec.js)0
-rw-r--r--spec/frontend/notebook/cells/output/index_spec.js (renamed from spec/javascripts/notebook/cells/output/index_spec.js)10
-rw-r--r--spec/frontend/notebook/cells/prompt_spec.js (renamed from spec/javascripts/notebook/cells/prompt_spec.js)4
-rw-r--r--spec/frontend/notebook/index_spec.js (renamed from spec/javascripts/notebook/index_spec.js)6
-rw-r--r--spec/helpers/projects/alert_management_helper_spec.rb26
-rw-r--r--spec/javascripts/diffs/create_diffs_store.js5
-rw-r--r--spec/javascripts/diffs/mock_data/diff_discussions.js5
-rw-r--r--spec/javascripts/diffs/mock_data/diff_file.js5
-rw-r--r--spec/javascripts/diffs/mock_data/diff_file_unreadable.js5
-rw-r--r--spec/javascripts/diffs/mock_data/diff_with_commit.js7
-rw-r--r--spec/javascripts/diffs/mock_data/merge_request_diffs.js7
-rw-r--r--spec/javascripts/helpers/init_vue_mr_page_helper.js2
-rw-r--r--spec/presenters/projects/prometheus/alert_presenter_spec.rb142
39 files changed, 491 insertions, 138 deletions
diff --git a/app/assets/javascripts/design_management/pages/design/index.vue b/app/assets/javascripts/design_management/pages/design/index.vue
index d51bdc4687a..3e56379dc47 100644
--- a/app/assets/javascripts/design_management/pages/design/index.vue
+++ b/app/assets/javascripts/design_management/pages/design/index.vue
@@ -35,6 +35,7 @@ import {
UPDATE_NOTE_ERROR,
designDeletionError,
} from '../../utils/error_messages';
+import { trackDesignDetailView } from '../../utils/tracking';
import { DESIGNS_ROUTE_NAME } from '../../router/constants';
export default {
@@ -257,8 +258,21 @@ export default {
query: this.$route.query,
});
},
+ trackEvent() {
+ trackDesignDetailView(
+ 'issue-design-collection',
+ this.$route.query.version || this.latestVersionId,
+ this.isLatestVersion,
+ );
+ },
+ },
+ beforeRouteEnter(to, from, next) {
+ next(vm => {
+ vm.trackEvent();
+ });
},
beforeRouteUpdate(to, from, next) {
+ this.trackEvent();
this.closeCommentForm();
next();
},
diff --git a/app/assets/javascripts/design_management/utils/tracking.js b/app/assets/javascripts/design_management/utils/tracking.js
new file mode 100644
index 00000000000..c94aa83ecc0
--- /dev/null
+++ b/app/assets/javascripts/design_management/utils/tracking.js
@@ -0,0 +1,22 @@
+import Tracking from '~/tracking';
+
+function assembleDesignPayload(payloadArr) {
+ return {
+ value: {
+ 'internal-object-refrerer': payloadArr[0],
+ 'version-number': payloadArr[1],
+ 'current-version': payloadArr[2],
+ },
+ };
+}
+
+// Tracking Constants
+const DESIGN_TRACKING_PAGE_NAME = 'projects:issues:design';
+
+// eslint-disable-next-line import/prefer-default-export
+export function trackDesignDetailView(refrerer = '', designVersion = 1, latestVersion = false) {
+ Tracking.event(DESIGN_TRACKING_PAGE_NAME, 'design_viewed', {
+ label: 'design_viewed',
+ ...assembleDesignPayload([refrerer, designVersion, latestVersion]),
+ });
+}
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 6eb010c4882..d759983dafa 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -86,11 +86,13 @@ class Projects::IssuesController < Projects::ApplicationController
)
build_params = issue_params.merge(
merge_request_to_resolve_discussions_of: params[:merge_request_to_resolve_discussions_of],
- discussion_to_resolve: params[:discussion_to_resolve]
+ discussion_to_resolve: params[:discussion_to_resolve],
+ confidential: !!Gitlab::Utils.to_boolean(params[:issue][:confidential])
)
service = Issues::BuildService.new(project, current_user, build_params)
@issue = @noteable = service.execute
+
@merge_request_to_resolve_discussions_of = service.merge_request_to_resolve_discussions_of
@discussion_to_resolve = service.discussions_to_resolve.first if params[:discussion_to_resolve]
diff --git a/app/helpers/projects/alert_management_helper.rb b/app/helpers/projects/alert_management_helper.rb
index 17f5a400eec..b2bb32239aa 100644
--- a/app/helpers/projects/alert_management_helper.rb
+++ b/app/helpers/projects/alert_management_helper.rb
@@ -7,7 +7,7 @@ module Projects::AlertManagementHelper
'enable-alert-management-path' => edit_project_service_path(project, AlertsService),
'empty-alert-svg-path' => image_path('illustrations/alert-management-empty-state.svg'),
'user-can-enable-alert-management' => can?(current_user, :admin_project, project).to_s,
- 'alert-management-enabled' => Feature.enabled?(:alert_management_minimal, project).to_s
+ 'alert-management-enabled' => (!!project.alerts_service_activated?).to_s
}
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 5f614d30e2d..9eac01c3c06 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -1436,20 +1436,12 @@ class Project < ApplicationRecord
# Expires various caches before a project is renamed.
def expire_caches_before_rename(old_path)
- repo = Repository.new(old_path, self, shard: repository_storage)
- wiki = Repository.new("#{old_path}.wiki", self, shard: repository_storage, repo_type: Gitlab::GlRepository::WIKI)
- design = Repository.new("#{old_path}#{Gitlab::GlRepository::DESIGN.path_suffix}", self, shard: repository_storage, repo_type: Gitlab::GlRepository::DESIGN)
+ project_repo = Repository.new(old_path, self, shard: repository_storage)
+ wiki_repo = Repository.new("#{old_path}#{Gitlab::GlRepository::WIKI.path_suffix}", self, shard: repository_storage, repo_type: Gitlab::GlRepository::WIKI)
+ design_repo = Repository.new("#{old_path}#{Gitlab::GlRepository::DESIGN.path_suffix}", self, shard: repository_storage, repo_type: Gitlab::GlRepository::DESIGN)
- if repo.exists?
- repo.before_delete
- end
-
- if wiki.exists?
- wiki.before_delete
- end
-
- if design.exists?
- design.before_delete
+ [project_repo, wiki_repo, design_repo].each do |repo|
+ repo.before_delete if repo.exists?
end
end
diff --git a/app/presenters/projects/prometheus/alert_presenter.rb b/app/presenters/projects/prometheus/alert_presenter.rb
index c03925c0871..2114e06a8c5 100644
--- a/app/presenters/projects/prometheus/alert_presenter.rb
+++ b/app/presenters/projects/prometheus/alert_presenter.rb
@@ -7,6 +7,7 @@ module Projects
GENERIC_ALERT_SUMMARY_ANNOTATIONS = %w(monitoring_tool service hosts).freeze
MARKDOWN_LINE_BREAK = " \n".freeze
INCIDENT_LABEL_NAME = IncidentManagement::CreateIssueService::INCIDENT_LABEL[:title].freeze
+ METRIC_TIME_WINDOW = 30.minutes
def full_title
[environment_name, alert_title].compact.join(': ')
@@ -119,9 +120,63 @@ module Projects
Array(hosts.value).join(' ')
end
- def metric_embed_for_alert; end
+ def metric_embed_for_alert
+ url = embed_url_for_gitlab_alert || embed_url_for_self_managed_alert
+
+ "\n[](#{url})" if url
+ end
+
+ def embed_url_for_gitlab_alert
+ return unless gitlab_alert
+
+ metrics_dashboard_project_prometheus_alert_url(
+ project,
+ gitlab_alert.prometheus_metric_id,
+ environment_id: environment.id,
+ **alert_embed_window_params(embed_time)
+ )
+ end
+
+ def embed_url_for_self_managed_alert
+ return unless environment && full_query && title
+
+ metrics_dashboard_project_environment_url(
+ project,
+ environment,
+ embed_json: dashboard_for_self_managed_alert.to_json,
+ **alert_embed_window_params(embed_time)
+ )
+ end
+
+ def embed_time
+ starts_at ? Time.rfc3339(starts_at) : Time.current
+ end
+
+ def alert_embed_window_params(time)
+ {
+ start: format_embed_timestamp(time - METRIC_TIME_WINDOW),
+ end: format_embed_timestamp(time + METRIC_TIME_WINDOW)
+ }
+ end
+
+ def format_embed_timestamp(time)
+ time.utc.strftime('%FT%TZ')
+ end
+
+ def dashboard_for_self_managed_alert
+ {
+ panel_groups: [{
+ panels: [{
+ type: 'line-graph',
+ title: title,
+ y_label: y_label,
+ metrics: [{
+ query_range: full_query
+ }]
+ }]
+ }]
+ }
+ end
end
end
end
-
-Projects::Prometheus::AlertPresenter.prepend_if_ee('EE::Projects::Prometheus::AlertPresenter')
diff --git a/app/services/issues/build_service.rb b/app/services/issues/build_service.rb
index daef468987e..e62315de5f9 100644
--- a/app/services/issues/build_service.rb
+++ b/app/services/issues/build_service.rb
@@ -65,15 +65,19 @@ module Issues
private
def whitelisted_issue_params
+ base_params = [:title, :description, :confidential]
+ admin_params = [:milestone_id]
+
if can?(current_user, :admin_issue, project)
- params.slice(:title, :description, :milestone_id)
+ params.slice(*(base_params + admin_params))
else
- params.slice(:title, :description)
+ params.slice(*base_params)
end
end
def build_issue_params
- issue_params_with_info_from_discussions.merge(whitelisted_issue_params)
+ { author: current_user }.merge(issue_params_with_info_from_discussions)
+ .merge(whitelisted_issue_params)
end
end
end
diff --git a/changelogs/unreleased/216472-move-embeding-metrics-to-core.yml b/changelogs/unreleased/216472-move-embeding-metrics-to-core.yml
new file mode 100644
index 00000000000..bd3dcda4c89
--- /dev/null
+++ b/changelogs/unreleased/216472-move-embeding-metrics-to-core.yml
@@ -0,0 +1,5 @@
+---
+title: Moves embedded metrics for Prometheus alerts to Core
+merge_request: 31203
+author:
+type: changed
diff --git a/changelogs/unreleased/add_confidential_issue_url_param.yml b/changelogs/unreleased/add_confidential_issue_url_param.yml
new file mode 100644
index 00000000000..bb3ce4166e6
--- /dev/null
+++ b/changelogs/unreleased/add_confidential_issue_url_param.yml
@@ -0,0 +1,5 @@
+---
+title: Adds URL parameter for confidential new issue creation
+merge_request: 30250
+author:
+type: added
diff --git a/doc/.vale/gitlab/BadgeCapitalization.yml b/doc/.vale/gitlab/BadgeCapitalization.yml
new file mode 100644
index 00000000000..7e68a06b4d5
--- /dev/null
+++ b/doc/.vale/gitlab/BadgeCapitalization.yml
@@ -0,0 +1,42 @@
+---
+# Verifies that badges are not lower case, which won't render properly.
+#
+# For a list of all options, see https://errata-ai.github.io/vale/styles/
+extends: existence
+message: 'Badge "%s" must be capitalized.'
+link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#product-badges
+level: error
+scope: raw
+raw:
+ - '(\*\*\(Core\)\*\*|'
+ - '\*\*\(core\)\*\*|'
+ - '\*\*\(Starter\)\*\*|'
+ - '\*\*\(starter\)\*\*|'
+ - '\*\*\(Premium\)\*\*|'
+ - '\*\*\(premium\)\*\*|'
+ - '\*\*\(Ultimate\)\*\*|'
+ - '\*\*\(ultimate\)\*\*|'
+ - '\*\*\(Core Only\)\*\*|'
+ - '\*\*\(Core only\)\*\*|'
+ - '\*\*\(core only\)\*\*|'
+ - '\*\*\(Starter Only\)\*\*|'
+ - '\*\*\(Starter only\)\*\*|'
+ - '\*\*\(starter only\)\*\*|'
+ - '\*\*\(Premium Only\)\*\*|'
+ - '\*\*\(Premium only\)\*\*|'
+ - '\*\*\(premium only\)\*\*|'
+ - '\*\*\(Ultimate Only\)\*\*|'
+ - '\*\*\(Ultimate only\)\*\*|'
+ - '\*\*\(ultimate only\)\*\*|'
+ - '\*\*\(Free Only\)\*\*|'
+ - '\*\*\(Free only\)\*\*|'
+ - '\*\*\(free only\)\*\*|'
+ - '\*\*\(Bronze Only\)\*\*|'
+ - '\*\*\(Bronze only\)\*\*|'
+ - '\*\*\(bronze only\)\*\*|'
+ - '\*\*\(Silver Only\)\*\*|'
+ - '\*\*\(Silver only\)\*\*|'
+ - '\*\*\(silver only\)\*\*|'
+ - '\*\*\(Gold Only\)\*\*|'
+ - '\*\*\(Gold only\)\*\*|'
+ - '\*\*\(gold only\)\*\*)'
diff --git a/doc/user/application_security/dast/index.md b/doc/user/application_security/dast/index.md
index f4c0764ae0b..bbb551748c6 100644
--- a/doc/user/application_security/dast/index.md
+++ b/doc/user/application_security/dast/index.md
@@ -140,7 +140,7 @@ The only changes to the site should be from the DAST scanner. Be aware that any
changes that users, scheduled tasks, database changes, code changes, other pipelines, or other scanners make to
the site during a scan could lead to inaccurate results.
-### Authenticated scan
+### Authentication
It's also possible to authenticate the user before performing the DAST checks:
diff --git a/doc/user/group/epics/img/epic_view_v12.3.png b/doc/user/group/epics/img/epic_view_v12.3.png
deleted file mode 100644
index 79758cf3d52..00000000000
--- a/doc/user/group/epics/img/epic_view_v12.3.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/epics/img/epic_view_v13.0.png b/doc/user/group/epics/img/epic_view_v13.0.png
new file mode 100644
index 00000000000..84fb835d6c6
--- /dev/null
+++ b/doc/user/group/epics/img/epic_view_v13.0.png
Binary files differ
diff --git a/doc/user/group/epics/index.md b/doc/user/group/epics/index.md
index f039a21f195..e9d27fdbdd5 100644
--- a/doc/user/group/epics/index.md
+++ b/doc/user/group/epics/index.md
@@ -58,7 +58,7 @@ An epic's page contains the following tabs:
- Hover over the total counts to see a breakdown of open and closed items.
- **Roadmap**: a roadmap view of child epics which have start and due dates.
-![epic view](img/epic_view_v12.3.png)
+![epic view](img/epic_view_v13.0.png)
## Adding an issue to an epic
@@ -75,6 +75,7 @@ the issue is automatically unlinked from its current parent.
To add an issue to an epic:
+1. Click the **Add** dropdown button.
1. Click **Add an issue**.
1. Identify the issue to be added, using either of the following methods:
- Paste the link of the issue.
@@ -91,7 +92,7 @@ Creating an issue from an epic enables you to maintain focus on the broader cont
To create an issue from an epic:
-1. On the epic's page, under **Epics and Issues**, click the arrow next to **Add an issue** and select **Create new issue**.
+1. On the epic's page, under **Epics and Issues**, click the **Add** dropdown button and select **Create new issue**.
1. Under **Title**, enter the title for the new issue.
1. From the **Project** dropdown, select the project in which the issue should be created.
1. Click **Create issue**.
@@ -128,6 +129,7 @@ the maximum depth being 5.
To add a child epic to an epic:
+1. Click the **Add** dropdown button.
1. Click **Add an epic**.
1. Identify the epic to be added, using either of the following methods:
- Paste the link of the epic.
diff --git a/doc/user/project/issues/managing_issues.md b/doc/user/project/issues/managing_issues.md
index b68efe89cc2..290e4f81ca3 100644
--- a/doc/user/project/issues/managing_issues.md
+++ b/doc/user/project/issues/managing_issues.md
@@ -92,9 +92,17 @@ field values using query string parameters in a URL. This is useful for embeddin
a URL in an external HTML page, and also certain scenarios where you want the user to
create an issue with certain fields prefilled.
-The title, description, and description template fields can be prefilled using
-this method. You cannot pre-fill both the description and description template fields
-in the same URL (since a description template also populates the description field).
+The title, description, description template, and confidential fields can be prefilled
+using this method. You cannot pre-fill both the description and description template
+fields in the same URL (since a description template also populates the description
+field).
+
+| Field | URL Parameter Name | Notes |
+|----------------------|-----------------------|-------------------------------------------------------|
+| title | `issue[title]` | |
+| description | `issue[description]` | |
+| description template | `issuable_template` | |
+| confidential | `issue[confidential]` | Parameter value must be `true` to set to confidential |
Follow these examples to form your new issue URL with prefilled fields.
@@ -102,6 +110,8 @@ Follow these examples to form your new issue URL with prefilled fields.
and a pre-filled description, the URL would be `https://gitlab.com/gitlab-org/gitlab-foss/issues/new?issue[title]=Validate%20new%20concept&issue[description]=Research%20idea`
- For a new issue in the GitLab Community Edition project with a pre-filled title
and a pre-filled description template, the URL would be `https://gitlab.com/gitlab-org/gitlab-foss/issues/new?issue[title]=Validate%20new%20concept&issuable_template=Research%20proposal`
+- For a new issue in the GitLab Community Edition project with a pre-filled title,
+ a pre-filled description, and the confidential flag set, the URL would be `https://gitlab.com/gitlab-org/gitlab-foss/issues/new?issue[title]=Validate%20new%20concept&issue[description]=Research%20idea&issue[confidential]=true`
## Moving Issues
diff --git a/lib/gitlab/prometheus_client.rb b/lib/gitlab/prometheus_client.rb
index e3559644142..b03d8a4d254 100644
--- a/lib/gitlab/prometheus_client.rb
+++ b/lib/gitlab/prometheus_client.rb
@@ -163,7 +163,7 @@ module Gitlab
end
def parse_json(response_body)
- Gitlab::Json.parse(response_body)
+ Gitlab::Json.parse(response_body, legacy_mode: true)
rescue JSON::ParserError
raise PrometheusClient::Error, 'Parsing response failed'
end
diff --git a/lib/mattermost/client.rb b/lib/mattermost/client.rb
index 01a9567491f..a9551ffbd30 100644
--- a/lib/mattermost/client.rb
+++ b/lib/mattermost/client.rb
@@ -49,7 +49,7 @@ module Mattermost
end
def json_response(response)
- json_response = Gitlab::Json.parse(response.body)
+ json_response = Gitlab::Json.parse(response.body, legacy_mode: true)
unless response.success?
raise Mattermost::ClientError.new(json_response['message'] || 'Undefined error')
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index ab0866da9de..57a437781fd 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -1191,6 +1191,9 @@ msgstr ""
msgid "Add a link"
msgstr ""
+msgid "Add a new issue"
+msgstr ""
+
msgid "Add a numbered list"
msgstr ""
@@ -1206,7 +1209,7 @@ msgstr ""
msgid "Add an SSH key"
msgstr ""
-msgid "Add an existing issue to the epic."
+msgid "Add an existing issue"
msgstr ""
msgid "Add an issue"
@@ -6153,9 +6156,6 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
-msgid "Create a new issue and add it to the epic."
-msgstr ""
-
msgid "Create a new repository"
msgstr ""
@@ -6165,9 +6165,6 @@ msgstr ""
msgid "Create an account using:"
msgstr ""
-msgid "Create an issue"
-msgstr ""
-
msgid "Create an issue. Issues are created for each alert triggered."
msgstr ""
@@ -8324,10 +8321,10 @@ msgstr ""
msgid "Epics, Issues, and Merge Requests"
msgstr ""
-msgid "Epics|Add an epic"
+msgid "Epics|Add a new epic"
msgstr ""
-msgid "Epics|Add an existing epic as a child epic."
+msgid "Epics|Add an existing epic"
msgstr ""
msgid "Epics|An error occurred while saving the %{epicDateType} date"
@@ -8339,12 +8336,6 @@ msgstr ""
msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
msgstr ""
-msgid "Epics|Create an epic within this group and add it as a child epic."
-msgstr ""
-
-msgid "Epics|Create new epic"
-msgstr ""
-
msgid "Epics|How can I solve this?"
msgstr ""
diff --git a/scripts/rspec_helpers.sh b/scripts/rspec_helpers.sh
index e0cce46fb6b..622389f34b6 100644
--- a/scripts/rspec_helpers.sh
+++ b/scripts/rspec_helpers.sh
@@ -73,6 +73,12 @@ function rspec_paralellized_job() {
export KNAPSACK_LOG_LEVEL="debug"
export KNAPSACK_REPORT_PATH="knapsack/${report_name}_report.json"
+ # There's a bug where artifacts are sometimes not downloaded. Since specs can run without the Knapsack report, we can
+ # handle the missing artifact gracefully here. See https://gitlab.com/gitlab-org/gitlab/-/issues/212349.
+ if [[ ! -f "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" ]]; then
+ echo "{}" > "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}"
+ fi
+
cp "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" "${KNAPSACK_REPORT_PATH}"
if [[ -z "${KNAPSACK_TEST_FILE_PATTERN}" ]]; then
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index a2df023fe4c..053932944bb 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -187,6 +187,33 @@ describe Projects::IssuesController do
expect(assigns(:issue)).to be_a_new(Issue)
end
+ where(:conf_value, :conf_result) do
+ [
+ [true, true],
+ ['true', true],
+ ['TRUE', true],
+ [false, false],
+ ['false', false],
+ ['FALSE', false]
+ ]
+ end
+
+ with_them do
+ it 'sets the confidential flag to the expected value' do
+ get :new, params: {
+ namespace_id: project.namespace,
+ project_id: project,
+ issue: {
+ confidential: conf_value
+ }
+ }
+
+ assigned_issue = assigns(:issue)
+ expect(assigned_issue).to be_a_new(Issue)
+ expect(assigned_issue.confidential).to eq conf_result
+ end
+ end
+
it 'fills in an issue for a merge request' do
project_with_repository = create(:project, :repository)
project_with_repository.add_developer(user)
diff --git a/spec/frontend/design_management/router_spec.js b/spec/frontend/design_management/router_spec.js
index fc88bfa06d2..0f4afa5e288 100644
--- a/spec/frontend/design_management/router_spec.js
+++ b/spec/frontend/design_management/router_spec.js
@@ -1,4 +1,5 @@
import { mount, createLocalVue } from '@vue/test-utils';
+import { nextTick } from 'vue';
import VueRouter from 'vue-router';
import App from '~/design_management/components/app.vue';
import Designs from '~/design_management/pages/index.vue';
@@ -11,74 +12,66 @@ import {
} from '~/design_management/router/constants';
import '~/commons/bootstrap';
-jest.mock('mousetrap', () => ({
- bind: jest.fn(),
- unbind: jest.fn(),
-}));
-
-describe('Design management router', () => {
- let vm;
- let router;
-
- function factory() {
- const localVue = createLocalVue();
-
- localVue.use(VueRouter);
+function factory(routeArg) {
+ const localVue = createLocalVue();
+ localVue.use(VueRouter);
- window.gon = { sprite_icons: '' };
+ window.gon = { sprite_icons: '' };
- router = createRouter('/');
+ const router = createRouter('/');
+ if (routeArg !== undefined) {
+ router.push(routeArg);
+ }
- vm = mount(App, {
- localVue,
- router,
- mocks: {
- $apollo: {
- queries: {
- designs: { loading: true },
- design: { loading: true },
- permissions: { loading: true },
- },
+ return mount(App, {
+ localVue,
+ router,
+ mocks: {
+ $apollo: {
+ queries: {
+ designs: { loading: true },
+ design: { loading: true },
+ permissions: { loading: true },
},
},
- });
- }
-
- beforeEach(() => {
- factory();
+ },
});
+}
- afterEach(() => {
- vm.destroy();
+jest.mock('mousetrap', () => ({
+ bind: jest.fn(),
+ unbind: jest.fn(),
+}));
- router.app.$destroy();
+describe('Design management router', () => {
+ afterEach(() => {
window.location.hash = '';
});
- describe.each([['/'], [{ name: ROOT_ROUTE_NAME }]])('root route', pushArg => {
+ describe.each([['/'], [{ name: ROOT_ROUTE_NAME }]])('root route', routeArg => {
it('pushes home component', () => {
- router.push(pushArg);
+ const wrapper = factory(routeArg);
- expect(vm.find(Designs).exists()).toBe(true);
+ expect(wrapper.find(Designs).exists()).toBe(true);
});
});
- describe.each([['/designs'], [{ name: DESIGNS_ROUTE_NAME }]])('designs route', pushArg => {
+ describe.each([['/designs'], [{ name: DESIGNS_ROUTE_NAME }]])('designs route', routeArg => {
it('pushes designs root component', () => {
- router.push(pushArg);
+ const wrapper = factory(routeArg);
- expect(vm.find(Designs).exists()).toBe(true);
+ expect(wrapper.find(Designs).exists()).toBe(true);
});
});
describe.each([['/designs/1'], [{ name: DESIGN_ROUTE_NAME, params: { id: '1' } }]])(
'designs detail route',
- pushArg => {
+ routeArg => {
it('pushes designs detail component', () => {
- router.push(pushArg);
+ const wrapper = factory(routeArg);
- return vm.vm.$nextTick().then(() => {
- const detail = vm.find(DesignDetail);
+ return nextTick().then(() => {
+ const detail = wrapper.find(DesignDetail);
expect(detail.exists()).toBe(true);
expect(detail.props('id')).toEqual('1');
});
diff --git a/spec/frontend/design_management/utils/tracking_spec.js b/spec/frontend/design_management/utils/tracking_spec.js
new file mode 100644
index 00000000000..ab540587c01
--- /dev/null
+++ b/spec/frontend/design_management/utils/tracking_spec.js
@@ -0,0 +1,51 @@
+import { mockTracking } from 'helpers/tracking_helper';
+import { trackDesignDetailView } from '~/design_management/utils/tracking';
+
+function getTrackingSpy(key) {
+ return mockTracking(key, undefined, jest.spyOn);
+}
+
+describe('Tracking Events', () => {
+ describe('trackDesignDetailView', () => {
+ const eventKey = 'projects:issues:design';
+ const eventName = 'design_viewed';
+
+ it('trackDesignDetailView fires a tracking event when called', () => {
+ const trackingSpy = getTrackingSpy(eventKey);
+
+ trackDesignDetailView();
+
+ expect(trackingSpy).toHaveBeenCalledWith(
+ eventKey,
+ eventName,
+ expect.objectContaining({
+ label: eventName,
+ value: {
+ 'internal-object-refrerer': '',
+ 'version-number': 1,
+ 'current-version': false,
+ },
+ }),
+ );
+ });
+
+ it('trackDesignDetailView allows to customize the value payload', () => {
+ const trackingSpy = getTrackingSpy(eventKey);
+
+ trackDesignDetailView('from-a-test', 100, true);
+
+ expect(trackingSpy).toHaveBeenCalledWith(
+ eventKey,
+ eventName,
+ expect.objectContaining({
+ label: eventName,
+ value: {
+ 'internal-object-refrerer': 'from-a-test',
+ 'version-number': 100,
+ 'current-version': true,
+ },
+ }),
+ );
+ });
+ });
+});
diff --git a/spec/frontend/diffs/components/diff_content_spec.js b/spec/frontend/diffs/components/diff_content_spec.js
index 979c67787f7..b78895f9e55 100644
--- a/spec/frontend/diffs/components/diff_content_spec.js
+++ b/spec/frontend/diffs/components/diff_content_spec.js
@@ -10,7 +10,7 @@ import ImageDiffOverlay from '~/diffs/components/image_diff_overlay.vue';
import NoteForm from '~/notes/components/note_form.vue';
import DiffDiscussions from '~/diffs/components/diff_discussions.vue';
import { IMAGE_DIFF_POSITION_TYPE } from '~/diffs/constants';
-import diffFileMockData from '../../../javascripts/diffs/mock_data/diff_file';
+import diffFileMockData from '../mock_data/diff_file';
import { diffViewerModes } from '~/ide/constants';
const localVue = createLocalVue();
diff --git a/spec/javascripts/notebook/cells/code_spec.js b/spec/frontend/notebook/cells/code_spec.js
index f3f97145ad3..3c9aea4a61a 100644
--- a/spec/javascripts/notebook/cells/code_spec.js
+++ b/spec/frontend/notebook/cells/code_spec.js
@@ -25,7 +25,7 @@ describe('Code component', () => {
beforeEach(done => {
vm = setupComponent(json.cells[0]);
- setTimeout(() => {
+ setImmediate(() => {
done();
});
});
@@ -39,7 +39,7 @@ describe('Code component', () => {
beforeEach(done => {
vm = setupComponent(json.cells[2]);
- setTimeout(() => {
+ setImmediate(() => {
done();
});
});
@@ -60,7 +60,7 @@ describe('Code component', () => {
vm = setupComponent(cell);
- setTimeout(() => {
+ setImmediate(() => {
done();
});
});
diff --git a/spec/javascripts/notebook/cells/markdown_spec.js b/spec/frontend/notebook/cells/markdown_spec.js
index 07b18d97cd9..359ac90a3ef 100644
--- a/spec/javascripts/notebook/cells/markdown_spec.js
+++ b/spec/frontend/notebook/cells/markdown_spec.js
@@ -24,7 +24,7 @@ describe('Markdown component', () => {
});
vm.$mount();
- setTimeout(() => {
+ setImmediate(() => {
done();
});
});
diff --git a/spec/javascripts/notebook/cells/output/html_sanitize_tests.js b/spec/frontend/notebook/cells/output/html_sanitize_tests.js
index 74c48f04367..74c48f04367 100644
--- a/spec/javascripts/notebook/cells/output/html_sanitize_tests.js
+++ b/spec/frontend/notebook/cells/output/html_sanitize_tests.js
diff --git a/spec/javascripts/notebook/cells/output/html_spec.js b/spec/frontend/notebook/cells/output/html_spec.js
index 3ee404fb187..3ee404fb187 100644
--- a/spec/javascripts/notebook/cells/output/html_spec.js
+++ b/spec/frontend/notebook/cells/output/html_spec.js
diff --git a/spec/javascripts/notebook/cells/output/index_spec.js b/spec/frontend/notebook/cells/output/index_spec.js
index 005569f1c2d..2b1aa5317c5 100644
--- a/spec/javascripts/notebook/cells/output/index_spec.js
+++ b/spec/frontend/notebook/cells/output/index_spec.js
@@ -25,7 +25,7 @@ describe('Output component', () => {
beforeEach(done => {
createComponent(json.cells[2].outputs[0]);
- setTimeout(() => {
+ setImmediate(() => {
done();
});
});
@@ -43,7 +43,7 @@ describe('Output component', () => {
beforeEach(done => {
createComponent(json.cells[3].outputs[0]);
- setTimeout(() => {
+ setImmediate(() => {
done();
});
});
@@ -73,7 +73,7 @@ describe('Output component', () => {
beforeEach(done => {
createComponent(json.cells[5].outputs[0]);
- setTimeout(() => {
+ setImmediate(() => {
done();
});
});
@@ -87,7 +87,7 @@ describe('Output component', () => {
beforeEach(done => {
createComponent(json.cells[6].outputs[0]);
- setTimeout(() => {
+ setImmediate(() => {
done();
});
});
@@ -104,7 +104,7 @@ describe('Output component', () => {
it("renders as plain text when doesn't recognise other types", done => {
createComponent(json.cells[7].outputs[0]);
- setTimeout(() => {
+ setImmediate(() => {
expect(vm.$el.querySelector('pre')).not.toBeNull();
expect(vm.$el.textContent.trim()).toContain('testing');
diff --git a/spec/javascripts/notebook/cells/prompt_spec.js b/spec/frontend/notebook/cells/prompt_spec.js
index cbbcb1e68e3..cf5a7a603c6 100644
--- a/spec/javascripts/notebook/cells/prompt_spec.js
+++ b/spec/frontend/notebook/cells/prompt_spec.js
@@ -16,7 +16,7 @@ describe('Prompt component', () => {
});
vm.$mount();
- setTimeout(() => {
+ setImmediate(() => {
done();
});
});
@@ -40,7 +40,7 @@ describe('Prompt component', () => {
});
vm.$mount();
- setTimeout(() => {
+ setImmediate(() => {
done();
});
});
diff --git a/spec/javascripts/notebook/index_spec.js b/spec/frontend/notebook/index_spec.js
index 2e2ea5ad8af..36b092be976 100644
--- a/spec/javascripts/notebook/index_spec.js
+++ b/spec/frontend/notebook/index_spec.js
@@ -22,7 +22,7 @@ describe('Notebook component', () => {
});
vm.$mount();
- setTimeout(() => {
+ setImmediate(() => {
done();
});
});
@@ -42,7 +42,7 @@ describe('Notebook component', () => {
});
vm.$mount();
- setTimeout(() => {
+ setImmediate(() => {
done();
});
});
@@ -74,7 +74,7 @@ describe('Notebook component', () => {
});
vm.$mount();
- setTimeout(() => {
+ setImmediate(() => {
done();
});
});
diff --git a/spec/helpers/projects/alert_management_helper_spec.rb b/spec/helpers/projects/alert_management_helper_spec.rb
index e1b01f4c196..57d781d9cb3 100644
--- a/spec/helpers/projects/alert_management_helper_spec.rb
+++ b/spec/helpers/projects/alert_management_helper_spec.rb
@@ -13,6 +13,8 @@ describe Projects::AlertManagementHelper do
let(:user_can_enable_alert_management) { true }
let(:setting_path) { edit_project_service_path(project, AlertsService) }
+ subject(:data) { helper.alert_management_data(current_user, project) }
+
before do
allow(helper)
.to receive(:can?)
@@ -27,11 +29,33 @@ describe Projects::AlertManagementHelper do
'enable-alert-management-path' => setting_path,
'empty-alert-svg-path' => match_asset_path('/assets/illustrations/alert-management-empty-state.svg'),
'user-can-enable-alert-management' => 'true',
- 'alert-management-enabled' => 'true'
+ 'alert-management-enabled' => 'false'
)
end
end
+ context 'with alerts service' do
+ let_it_be(:alerts_service) { create(:alerts_service, project: project) }
+
+ context 'when alerts service is active' do
+ it 'enables alert management' do
+ expect(data).to include(
+ 'alert-management-enabled' => 'true'
+ )
+ end
+ end
+
+ context 'when alerts service is inactive' do
+ it 'disables alert management' do
+ alerts_service.update(active: false)
+
+ expect(data).to include(
+ 'alert-management-enabled' => 'false'
+ )
+ end
+ end
+ end
+
context 'when user does not have requisite enablement permissions' do
let(:user_can_enable_alert_management) { false }
diff --git a/spec/javascripts/diffs/create_diffs_store.js b/spec/javascripts/diffs/create_diffs_store.js
deleted file mode 100644
index 9df057dd8b2..00000000000
--- a/spec/javascripts/diffs/create_diffs_store.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// No new code should be added to this file. Instead, modify the
-// file this one re-exports from. For more detail about why, see:
-// https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/31349
-
-export { default } from '../../frontend/diffs/create_diffs_store';
diff --git a/spec/javascripts/diffs/mock_data/diff_discussions.js b/spec/javascripts/diffs/mock_data/diff_discussions.js
deleted file mode 100644
index 17586fddd0f..00000000000
--- a/spec/javascripts/diffs/mock_data/diff_discussions.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// No new code should be added to this file. Instead, modify the
-// file this one re-exports from. For more detail about why, see:
-// https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/31349
-
-export { default } from '../../../frontend/diffs/mock_data/diff_discussions';
diff --git a/spec/javascripts/diffs/mock_data/diff_file.js b/spec/javascripts/diffs/mock_data/diff_file.js
deleted file mode 100644
index 9dc365b7403..00000000000
--- a/spec/javascripts/diffs/mock_data/diff_file.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// No new code should be added to this file. Instead, modify the
-// file this one re-exports from. For more detail about why, see:
-// https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/31349
-
-export { default } from '../../../frontend/diffs/mock_data/diff_file';
diff --git a/spec/javascripts/diffs/mock_data/diff_file_unreadable.js b/spec/javascripts/diffs/mock_data/diff_file_unreadable.js
deleted file mode 100644
index 09a0dc61847..00000000000
--- a/spec/javascripts/diffs/mock_data/diff_file_unreadable.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// No new code should be added to this file. Instead, modify the
-// file this one re-exports from. For more detail about why, see:
-// https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/31349
-
-export { default } from '../../../frontend/diffs/mock_data/diff_file_unreadable';
diff --git a/spec/javascripts/diffs/mock_data/diff_with_commit.js b/spec/javascripts/diffs/mock_data/diff_with_commit.js
deleted file mode 100644
index c36b0239060..00000000000
--- a/spec/javascripts/diffs/mock_data/diff_with_commit.js
+++ /dev/null
@@ -1,7 +0,0 @@
-// No new code should be added to this file. Instead, modify the
-// file this one re-exports from. For more detail about why, see:
-// https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/31349
-
-import getDiffWithCommit from '../../../frontend/diffs/mock_data/diff_with_commit';
-
-export default getDiffWithCommit;
diff --git a/spec/javascripts/diffs/mock_data/merge_request_diffs.js b/spec/javascripts/diffs/mock_data/merge_request_diffs.js
deleted file mode 100644
index de29eb7e560..00000000000
--- a/spec/javascripts/diffs/mock_data/merge_request_diffs.js
+++ /dev/null
@@ -1,7 +0,0 @@
-// No new code should be added to this file. Instead, modify the
-// file this one re-exports from. For more detail about why, see:
-// https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/31349
-
-import diffsMockData from '../../../frontend/diffs/mock_data/merge_request_diffs';
-
-export default diffsMockData;
diff --git a/spec/javascripts/helpers/init_vue_mr_page_helper.js b/spec/javascripts/helpers/init_vue_mr_page_helper.js
index 04f969fcd2d..1ba08199764 100644
--- a/spec/javascripts/helpers/init_vue_mr_page_helper.js
+++ b/spec/javascripts/helpers/init_vue_mr_page_helper.js
@@ -2,7 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import initMRPage from '~/mr_notes/index';
import axios from '~/lib/utils/axios_utils';
import { userDataMock, notesDataMock, noteableDataMock } from '../../frontend/notes/mock_data';
-import diffFileMockData from '../diffs/mock_data/diff_file';
+import diffFileMockData from '../../frontend/diffs/mock_data/diff_file';
export default function initVueMRPage() {
const mrTestEl = document.createElement('div');
diff --git a/spec/presenters/projects/prometheus/alert_presenter_spec.rb b/spec/presenters/projects/prometheus/alert_presenter_spec.rb
index 85c73aa3533..967a0fb2c09 100644
--- a/spec/presenters/projects/prometheus/alert_presenter_spec.rb
+++ b/spec/presenters/projects/prometheus/alert_presenter_spec.rb
@@ -152,6 +152,148 @@ describe Projects::Prometheus::AlertPresenter do
end
end
end
+
+ context 'with embedded metrics' do
+ let(:starts_at) { '2018-03-12T09:06:00Z' }
+
+ shared_examples_for 'markdown with metrics embed' do
+ let(:expected_markdown) do
+ <<~MARKDOWN.chomp
+ #### Summary
+
+ **Start time:** #{presenter.starts_at}#{markdown_line_break}
+ **full_query:** `avg(metric) > 1.0`
+
+ [](#{url})
+ MARKDOWN
+ end
+
+ context 'without a starting time available' do
+ around do |example|
+ Timecop.freeze(starts_at) { example.run }
+ end
+
+ it { is_expected.to eq(expected_markdown) }
+ end
+
+ context 'with a starting time available' do
+ before do
+ payload['startsAt'] = starts_at
+ end
+
+ it { is_expected.to eq(expected_markdown) }
+ end
+ end
+
+ context 'for gitlab-managed prometheus alerts' do
+ let(:gitlab_alert) { create(:prometheus_alert, project: project) }
+ let(:metric_id) { gitlab_alert.prometheus_metric_id }
+ let(:env_id) { gitlab_alert.environment_id }
+
+ before do
+ payload['labels'] = { 'gitlab_alert_id' => metric_id }
+ end
+
+ let(:url) { "http://localhost/#{project.full_path}/prometheus/alerts/#{metric_id}/metrics_dashboard?end=2018-03-12T09%3A36%3A00Z&environment_id=#{env_id}&start=2018-03-12T08%3A36%3A00Z" }
+
+ it_behaves_like 'markdown with metrics embed'
+ end
+
+ context 'for alerts from a self-managed prometheus' do
+ let!(:environment) { create(:environment, project: project, name: 'production') }
+ let(:url) { "http://localhost/#{project.full_path}/-/environments/#{environment.id}/metrics_dashboard?embed_json=#{CGI.escape(embed_content.to_json)}&end=2018-03-12T09%3A36%3A00Z&start=2018-03-12T08%3A36%3A00Z" }
+
+ let(:title) { 'title' }
+ let(:y_label) { 'y_label' }
+ let(:query) { 'avg(metric) > 1.0' }
+ let(:embed_content) do
+ {
+ panel_groups: [{
+ panels: [{
+ type: 'line-graph',
+ title: title,
+ y_label: y_label,
+ metrics: [{ query_range: query }]
+ }]
+ }]
+ }
+ end
+
+ before do
+ # Setup embed time range
+ payload['startsAt'] = starts_at
+
+ # Setup query
+ payload['generatorURL'] = "http://host?g0.expr=#{CGI.escape(query)}"
+
+ # Setup environment
+ payload['labels'] ||= {}
+ payload['labels']['gitlab_environment_name'] = 'production'
+
+ # Setup chart title & axis labels
+ payload['annotations'] ||= {}
+ payload['annotations']['title'] = 'title'
+ payload['annotations']['gitlab_y_label'] = 'y_label'
+ end
+
+ it_behaves_like 'markdown with metrics embed'
+
+ context 'without y_label' do
+ let(:y_label) { title }
+
+ before do
+ payload['annotations'].delete('gitlab_y_label')
+ end
+
+ it_behaves_like 'markdown with metrics embed'
+ end
+
+ context 'when not enough information is present for an embed' do
+ let(:expected_markdown) do
+ <<~MARKDOWN.chomp
+ #### Summary
+
+ **Start time:** #{presenter.starts_at}#{markdown_line_break}
+ **full_query:** `avg(metric) > 1.0`
+
+ MARKDOWN
+ end
+
+ context 'without title' do
+ before do
+ payload['annotations'].delete('title')
+ end
+
+ it { is_expected.to eq(expected_markdown) }
+ end
+
+ context 'without environment' do
+ before do
+ payload['labels'].delete('gitlab_environment_name')
+ end
+
+ it { is_expected.to eq(expected_markdown) }
+ end
+
+ context 'without full_query' do
+ let(:expected_markdown) do
+ <<~MARKDOWN.chomp
+ #### Summary
+
+ **Start time:** #{presenter.starts_at}
+
+ MARKDOWN
+ end
+
+ before do
+ payload.delete('generatorURL')
+ end
+
+ it { is_expected.to eq(expected_markdown) }
+ end
+ end
+ end
+ end
end
describe '#show_performance_dashboard_link?' do