summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml2
-rw-r--r--app/assets/stylesheets/components/dashboard_skeleton.scss8
-rw-r--r--app/controllers/projects/settings/operations_controller.rb2
-rw-r--r--app/models/project.rb2
-rw-r--r--app/models/project_metrics_setting.rb9
-rw-r--r--app/services/projects/operations/update_service.rb11
-rw-r--r--changelogs/unreleased/25604-add-dotnet-core-yaml-template.yml5
-rw-r--r--changelogs/unreleased/57171-add-dashboard-settings.yml5
-rw-r--r--config/locales/en.yml2
-rw-r--r--db/migrate/20190422082247_create_project_metrics_settings.rb14
-rw-r--r--db/schema.rb7
-rw-r--r--doc/administration/high_availability/nfs.md9
-rw-r--r--doc/ci/variables/predefined_variables.md4
-rw-r--r--doc/user/group/index.md23
-rw-r--r--lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml4
-rw-r--r--lib/gitlab/ci/templates/dotNET-Core.yml107
-rw-r--r--lib/gitlab/import_export/import_export.yml1
-rw-r--r--lib/gitlab/import_export/relation_factory.rb3
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb3
-rw-r--r--spec/controllers/projects/settings/operations_controller_spec.rb14
-rw-r--r--spec/factories/project_metrics_settings.rb8
-rw-r--r--spec/javascripts/fixtures/static/images/green_box.png (renamed from spec/javascripts/fixtures/images/green_box.png)bin1306 -> 1306 bytes
-rw-r--r--spec/javascripts/fixtures/static/images/one_white_pixel.png (renamed from spec/javascripts/fixtures/one_white_pixel.png)bin68 -> 68 bytes
-rw-r--r--spec/javascripts/fixtures/static/images/red_box.png (renamed from spec/javascripts/fixtures/images/red_box.png)bin1305 -> 1305 bytes
-rw-r--r--spec/javascripts/fixtures/static/projects.json (renamed from spec/javascripts/fixtures/projects.json)0
-rw-r--r--spec/javascripts/gl_dropdown_spec.js4
-rw-r--r--spec/javascripts/test_constants.js6
-rw-r--r--spec/javascripts/vue_shared/components/project_selector/project_list_item_spec.js4
-rw-r--r--spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js4
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml3
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml6
-rw-r--r--spec/models/project_metrics_setting_spec.rb55
-rw-r--r--spec/services/projects/operations/update_service_spec.rb50
33 files changed, 345 insertions, 30 deletions
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index bfefd42c52d..935b494b6f7 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -107,7 +107,7 @@ gitlab:ui:visual:
- $CI_COMMIT_MESSAGE =~ /\[skip visual\]/i
artifacts:
paths:
- - tests/__image_snapshots__/
+ - gitlab-ui/tests/__image_snapshots__/
when: always
karma:
diff --git a/app/assets/stylesheets/components/dashboard_skeleton.scss b/app/assets/stylesheets/components/dashboard_skeleton.scss
index 9775c329922..a104d035a9a 100644
--- a/app/assets/stylesheets/components/dashboard_skeleton.scss
+++ b/app/assets/stylesheets/components/dashboard_skeleton.scss
@@ -11,7 +11,7 @@
}
&-body {
- height: 120px;
+ min-height: 120px;
&-warning {
background-color: $orange-50;
@@ -22,10 +22,8 @@
}
}
- &-time-ago {
- &-icon {
- color: $gray-500;
- }
+ &-icon {
+ color: $gray-500;
}
&-footer {
diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb
index 1fafc33e917..5cfb0ac307d 100644
--- a/app/controllers/projects/settings/operations_controller.rb
+++ b/app/controllers/projects/settings/operations_controller.rb
@@ -56,6 +56,8 @@ module Projects
# overridden in EE
def permitted_project_params
{
+ metrics_setting_attributes: [:external_dashboard_url],
+
error_tracking_setting_attributes: [
:enabled,
:api_host,
diff --git a/app/models/project.rb b/app/models/project.rb
index 626ff9e1389..a29100405f9 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -188,6 +188,7 @@ class Project < ApplicationRecord
has_one :import_export_upload, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_one :project_repository, inverse_of: :project
has_one :error_tracking_setting, inverse_of: :project, class_name: 'ErrorTracking::ProjectErrorTrackingSetting'
+ has_one :metrics_setting, inverse_of: :project, class_name: 'ProjectMetricsSetting'
# Merge Requests for target project should be removed with it
has_many :merge_requests, foreign_key: 'target_project_id', inverse_of: :target_project
@@ -297,6 +298,7 @@ class Project < ApplicationRecord
reject_if: ->(attrs) { attrs[:id].blank? && attrs[:url].blank? }
accepts_nested_attributes_for :error_tracking_setting, update_only: true
+ accepts_nested_attributes_for :metrics_setting, update_only: true, allow_destroy: true
delegate :name, to: :owner, allow_nil: true, prefix: true
delegate :members, to: :team, prefix: true
diff --git a/app/models/project_metrics_setting.rb b/app/models/project_metrics_setting.rb
new file mode 100644
index 00000000000..a2a7dc571a4
--- /dev/null
+++ b/app/models/project_metrics_setting.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class ProjectMetricsSetting < ApplicationRecord
+ belongs_to :project
+
+ validates :external_dashboard_url,
+ length: { maximum: 255 },
+ addressable_url: { enforce_sanitization: true, ascii_only: true }
+end
diff --git a/app/services/projects/operations/update_service.rb b/app/services/projects/operations/update_service.rb
index aedf79c86d7..48eddb0e8d0 100644
--- a/app/services/projects/operations/update_service.rb
+++ b/app/services/projects/operations/update_service.rb
@@ -12,7 +12,16 @@ module Projects
private
def project_update_params
- error_tracking_params
+ error_tracking_params.merge(metrics_setting_params)
+ end
+
+ def metrics_setting_params
+ attribs = params[:metrics_setting_attributes]
+ return {} unless attribs
+
+ destroy = attribs[:external_dashboard_url].blank?
+
+ { metrics_setting_attributes: attribs.merge(_destroy: destroy) }
end
def error_tracking_params
diff --git a/changelogs/unreleased/25604-add-dotnet-core-yaml-template.yml b/changelogs/unreleased/25604-add-dotnet-core-yaml-template.yml
new file mode 100644
index 00000000000..ef9172aaf3b
--- /dev/null
+++ b/changelogs/unreleased/25604-add-dotnet-core-yaml-template.yml
@@ -0,0 +1,5 @@
+---
+title: Add .NET Core YAML template
+merge_request: 25604
+author: Piotr Wosiek
+type: added
diff --git a/changelogs/unreleased/57171-add-dashboard-settings.yml b/changelogs/unreleased/57171-add-dashboard-settings.yml
new file mode 100644
index 00000000000..f235872b35c
--- /dev/null
+++ b/changelogs/unreleased/57171-add-dashboard-settings.yml
@@ -0,0 +1,5 @@
+---
+title: Add backend support for a External Dashboard URL setting
+merge_request: 27550
+author:
+type: added
diff --git a/config/locales/en.yml b/config/locales/en.yml
index eb3b7771968..a3dceb2fb62 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -14,6 +14,8 @@ en:
token: "Auth Token"
project: "Project"
api_url: "Sentry API URL"
+ project/metrics_setting:
+ external_dashboard_url: "External dashboard URL"
errors:
messages:
label_already_exists_at_group_level: "already exists at group level for %{group}. Please choose another one."
diff --git a/db/migrate/20190422082247_create_project_metrics_settings.rb b/db/migrate/20190422082247_create_project_metrics_settings.rb
new file mode 100644
index 00000000000..3e21dd0a934
--- /dev/null
+++ b/db/migrate/20190422082247_create_project_metrics_settings.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class CreateProjectMetricsSettings < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ create_table :project_metrics_settings, id: :int, primary_key: :project_id, default: nil do |t|
+ t.string :external_dashboard_url, null: false
+ t.foreign_key :projects, column: :project_id, on_delete: :cascade
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 3a5d567ac57..23566a31a9d 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20190408163745) do
+ActiveRecord::Schema.define(version: 20190422082247) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -1681,6 +1681,10 @@ ActiveRecord::Schema.define(version: 20190408163745) do
t.index ["project_id"], name: "index_project_import_data_on_project_id", using: :btree
end
+ create_table "project_metrics_settings", primary_key: "project_id", id: :integer, default: nil, force: :cascade do |t|
+ t.string "external_dashboard_url", null: false
+ end
+
create_table "project_mirror_data", id: :serial, force: :cascade do |t|
t.integer "project_id", null: false
t.string "status"
@@ -2529,6 +2533,7 @@ ActiveRecord::Schema.define(version: 20190408163745) do
add_foreign_key "project_features", "projects", name: "fk_18513d9b92", on_delete: :cascade
add_foreign_key "project_group_links", "projects", name: "fk_daa8cee94c", on_delete: :cascade
add_foreign_key "project_import_data", "projects", name: "fk_ffb9ee3a10", on_delete: :cascade
+ add_foreign_key "project_metrics_settings", "projects", on_delete: :cascade
add_foreign_key "project_mirror_data", "projects", on_delete: :cascade
add_foreign_key "project_repositories", "projects", on_delete: :cascade
add_foreign_key "project_repositories", "shards", on_delete: :restrict
diff --git a/doc/administration/high_availability/nfs.md b/doc/administration/high_availability/nfs.md
index 72341a5c777..d0e0e320019 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/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md
index 40458137752..4e902c042e6 100644
--- a/doc/ci/variables/predefined_variables.md
+++ b/doc/ci/variables/predefined_variables.md
@@ -112,3 +112,7 @@ future GitLab releases.**
| `GITLAB_USER_NAME` | 10.0 | all | The real name of the user who started the job |
| `RESTORE_CACHE_ATTEMPTS` | 8.15 | 1.9 | Number of attempts to restore the cache running a job |
| `GITLAB_FEATURES` | 10.6 | all | The comma separated list of licensed features available for your instance and plan |
+
+[gitlab-deploy-token]: ../../user/project/deploy_tokens/index.md#gitlab-deploy-token
+[registry]: ../../user/project/container_registry.md
+[dependent-repositories]: ../../user/project/new_ci_build_permissions_model.md#dependent-repositories
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index 6054ab97dc1..2d887673fd6 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -68,7 +68,7 @@ together in a single list view.
You can create a group in GitLab from:
-1. The Groups page: expand the left menu, click **Groups**, and click the green button **New group**:
+1. The Groups page: from the top menu, click **Groups**, and click the green button **New group**:
![new group from groups page](img/new_group_from_groups.png)
@@ -80,14 +80,21 @@ Add the following information:
![new group info](img/create_new_group_info.png)
-1. Set the **Group path** which will be the **namespace** under which your projects
- will be hosted (path can contain only letters, digits, underscores, dashes
- and dots; it cannot start with dashes or end in dot).
-1. The **Group name** will populate with the path. Optionally, you can change
- it. This is the name that will display in the group views.
-1. Optionally, you can add a description so that others can briefly understand
+1. The **Group name** will populate the URL automatically. Optionally, you can change it.
+ This is the name that is displayed in the group views.
+ The name can contain only:
+ - Alphanumeric characters.
+ - Underscores.
+ - Dashes and dots.
+ - Spaces.
+1. The **Group URL**, which will be the namespace under which your projects will be hosted.
+ The URL can contain only:
+ - Alphanumeric characters.
+ - Underscores.
+ - Dashes and dots. It cannot start with dashes or end in dot.
+1. Optionally, you can add a brief description to tell others
what this group is about.
-1. Optionally, choose an avatar for your project.
+1. Optionally, choose an avatar for your group.
1. Choose the [visibility level](../../public_access/public_access.md).
## Add users to a group
diff --git a/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml
index 2a90cc9a06c..fd7fac5dcab 100644
--- a/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml
@@ -30,6 +30,7 @@ dast:
- |
function dast_run() {
docker run \
+ --env DAST_FULL_SCAN_ENABLED \
--env DAST_TARGET_AVAILABILITY_TIMEOUT \
--volume "$PWD:/output" \
--volume /var/run/docker.sock:/var/run/docker.sock \
@@ -46,7 +47,8 @@ dast:
--auth-username $DAST_USERNAME \
--auth-password $DAST_PASSWORD \
--auth-username-field $DAST_USERNAME_FIELD \
- --auth-password-field $DAST_PASSWORD_FIELD
+ --auth-password-field $DAST_PASSWORD_FIELD \
+ --auth-exclude-urls $DAST_AUTH_EXCLUDE_URLS
else
dast_run
fi
diff --git a/lib/gitlab/ci/templates/dotNET-Core.yml b/lib/gitlab/ci/templates/dotNET-Core.yml
new file mode 100644
index 00000000000..558ca3d22e1
--- /dev/null
+++ b/lib/gitlab/ci/templates/dotNET-Core.yml
@@ -0,0 +1,107 @@
+# This is a simple example illustrating how to build and test .NET Core project
+# with GitLab Continuous Integration / Continuous Delivery.
+
+# ### Specify the Docker image
+#
+# Instead of installing .NET Core SDK manually, a docker image is used
+# with already pre-installed .NET Core SDK.
+# The 'latest' tag targets the latest available version of .NET Core SDK image.
+# If preferred, you can explicitly specify version of .NET Core e.g. using '2.2-sdk' tag.
+#
+# See other available tags for .NET Core: https://hub.docker.com/r/microsoft/dotnet
+# Learn more about Docker tags: https://docs.docker.com/glossary/?term=tag
+# and the Docker itself: https://opensource.com/resources/what-docker
+image: microsoft/dotnet:latest
+
+# ### Define variables
+#
+variables:
+ # 1) Name of directory where restore and build objects are stored.
+ OBJECTS_DIRECTORY: 'obj'
+ # 2) Name of directory used for keeping restored dependencies.
+ NUGET_PACKAGES_DIRECTORY: '.nuget'
+ # 3) A relative path to the source code from project repository root.
+ # NOTE: Please edit this path so it matches the structure of your project!
+ SOURCE_CODE_PATH: '*/*/'
+
+# ### Define stage list
+#
+# In this example there are only two stages.
+# Initially, the project will be built and then tested.
+stages:
+ - build
+ - test
+
+# ### Define global cache rule
+#
+# Before building the project, all dependencies (e.g. third-party NuGet packages)
+# must be restored. Jobs on GitLab.com's Shared Runners are executed on autoscaled machines.
+# Each machine is used only once (for security reasons) and after that it is removed.
+# What that means is that before every job a dependency restore must be performed
+# because restored dependencies are removed along with machines. Fortunately,
+# GitLab provides cache mechanism with the aim of keeping restored dependencies
+# for other jobs. This example shows how to configure cache to pass over restored
+# dependencies for re-use.
+#
+# With global cache rule, cached dependencies will be downloaded before every job
+# and then unpacked to the paths as specified below.
+cache:
+ # Per-stage and per-branch caching.
+ key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG"
+ paths:
+ # Specify three paths that should be cached:
+ #
+ # 1) Main JSON file holding information about package dependency tree, packages versions,
+ # frameworks etc. It also holds information where to the dependencies were restored.
+ - '$SOURCE_CODE_PATH$OBJECTS_DIRECTORY/project.assets.json'
+ # 2) Other NuGet and MSBuild related files. Also needed.
+ - '$SOURCE_CODE_PATH$OBJECTS_DIRECTORY/*.csproj.nuget.*'
+ # 3) Path to the directory where restored dependencies are kept.
+ - '$NUGET_PACKAGES_DIRECTORY'
+ # 'pull-push' policy means that latest cache will be downloaded (if exists)
+ # before executing the job, and a newer version will be uploaded afterwards.
+ # Such setting saves time when there are no changes in referenced third-party
+ # packages. For example if you run a pipeline with changes in your code,
+ # but with no changes within third-party packages which your project is using,
+ # then project restore will happen in next to no time as all required dependencies
+ # will already be there — unzipped from cache. 'pull-push' policy is a default
+ # cache policy, you do not have to specify it explicitly.
+ policy: pull-push
+
+# ### Restore project dependencies
+#
+# NuGet packages by default are restored to '.nuget/packages' directory
+# in the user's home directory. That directory is out of scope of GitLab caching.
+# To get around this a custom path can be specified using '--packages <PATH>' option
+# for 'dotnet restore' command. In this example a temporary directory is created
+# in the root of project repository, so it's content can be cached.
+#
+# Learn more about GitLab cache: https://docs.gitlab.com/ee/ci/caching/index.html
+before_script:
+ - 'dotnet restore --packages $NUGET_PACKAGES_DIRECTORY'
+
+build:
+ stage: build
+ # ### Build all projects discovered from solution file.
+ #
+ # Note: this will fail if you have any projects in your solution that are not
+ # .NET Core based projects e.g. WCF service, which is based on .NET Framework,
+ # not .NET Core. In such scenario you will need to build every .NET Core based
+ # project by explicitly specifying a relative path to the directory
+ # where it is located e.g. 'dotnet build ./src/ConsoleApp'.
+ # Only one project path can be passed as a parameter to 'dotnet build' command.
+ script:
+ - 'dotnet build --no-restore'
+
+tests:
+ stage: test
+ # ### Run the tests
+ #
+ # You can either run tests for all test projects that are defined in your solution
+ # with 'dotnet test' or run tests only for specific project by specifying
+ # a relative path to the directory where it is located e.g. 'dotnet test ./test/UnitTests'.
+ #
+ # You may want to define separate testing jobs for different types of testing
+ # e.g. integration tests, unit tests etc.
+ script:
+ - 'dotnet test --no-restore'
diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml
index ce268793128..c6d4fda4af5 100644
--- a/lib/gitlab/import_export/import_export.yml
+++ b/lib/gitlab/import_export/import_export.yml
@@ -75,6 +75,7 @@ project_tree:
- :project_badges
- :ci_cd_settings
- :error_tracking_setting
+ - :metrics_setting
# Only include the following attributes for the models specified.
included_attributes:
diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb
index 61a1aa6da5a..e1e70a008d9 100644
--- a/lib/gitlab/import_export/relation_factory.rb
+++ b/lib/gitlab/import_export/relation_factory.rb
@@ -25,7 +25,8 @@ module Gitlab
metrics: 'MergeRequest::Metrics',
ci_cd_settings: 'ProjectCiCdSetting',
error_tracking_setting: 'ErrorTracking::ProjectErrorTrackingSetting',
- links: 'Releases::Link' }.freeze
+ links: 'Releases::Link',
+ metrics_setting: 'ProjectMetricsSetting' }.freeze
USER_REFERENCES = %w[author_id assignee_id updated_by_id merged_by_id latest_closed_by_id user_id created_by_id last_edited_by_id merge_user_id resolved_by_id closed_by_id].freeze
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb
index de5c535c757..10bba98f704 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb
@@ -2,7 +2,8 @@
module QA
context 'Create' do
- describe 'File templates' do
+ # Issue: https://gitlab.com/gitlab-org/quality/nightly/issues/97
+ describe 'File templates', :quarantine do
include Runtime::Fixtures
def login
diff --git a/spec/controllers/projects/settings/operations_controller_spec.rb b/spec/controllers/projects/settings/operations_controller_spec.rb
index 0dd73972098..aa9cd41ed19 100644
--- a/spec/controllers/projects/settings/operations_controller_spec.rb
+++ b/spec/controllers/projects/settings/operations_controller_spec.rb
@@ -166,6 +166,20 @@ describe Projects::Settings::OperationsController do
end
end
+ context 'metrics dashboard setting' do
+ describe 'PATCH #update' do
+ let(:params) do
+ {
+ metrics_setting_attributes: {
+ external_dashboard_url: 'https://gitlab.com'
+ }
+ }
+ end
+
+ it_behaves_like 'PATCHable'
+ end
+ end
+
private
def project_params(project, params = {})
diff --git a/spec/factories/project_metrics_settings.rb b/spec/factories/project_metrics_settings.rb
new file mode 100644
index 00000000000..234753f9b87
--- /dev/null
+++ b/spec/factories/project_metrics_settings.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :project_metrics_setting, class: ProjectMetricsSetting do
+ project
+ external_dashboard_url 'https://grafana.com'
+ end
+end
diff --git a/spec/javascripts/fixtures/images/green_box.png b/spec/javascripts/fixtures/static/images/green_box.png
index cd1ff9f9ade..cd1ff9f9ade 100644
--- a/spec/javascripts/fixtures/images/green_box.png
+++ b/spec/javascripts/fixtures/static/images/green_box.png
Binary files differ
diff --git a/spec/javascripts/fixtures/one_white_pixel.png b/spec/javascripts/fixtures/static/images/one_white_pixel.png
index 073fcf40a18..073fcf40a18 100644
--- a/spec/javascripts/fixtures/one_white_pixel.png
+++ b/spec/javascripts/fixtures/static/images/one_white_pixel.png
Binary files differ
diff --git a/spec/javascripts/fixtures/images/red_box.png b/spec/javascripts/fixtures/static/images/red_box.png
index 73b2927da0f..73b2927da0f 100644
--- a/spec/javascripts/fixtures/images/red_box.png
+++ b/spec/javascripts/fixtures/static/images/red_box.png
Binary files differ
diff --git a/spec/javascripts/fixtures/projects.json b/spec/javascripts/fixtures/static/projects.json
index 68a150f602a..68a150f602a 100644
--- a/spec/javascripts/fixtures/projects.json
+++ b/spec/javascripts/fixtures/static/projects.json
diff --git a/spec/javascripts/gl_dropdown_spec.js b/spec/javascripts/gl_dropdown_spec.js
index 57e31d933ca..8c7820ddb52 100644
--- a/spec/javascripts/gl_dropdown_spec.js
+++ b/spec/javascripts/gl_dropdown_spec.js
@@ -6,7 +6,7 @@ import '~/lib/utils/common_utils';
describe('glDropdown', function describeDropdown() {
preloadFixtures('static/gl_dropdown.html');
- loadJSONFixtures('projects.json');
+ loadJSONFixtures('static/projects.json');
const NON_SELECTABLE_CLASSES =
'.divider, .separator, .dropdown-header, .dropdown-menu-empty-item';
@@ -67,7 +67,7 @@ describe('glDropdown', function describeDropdown() {
loadFixtures('static/gl_dropdown.html');
this.dropdownContainerElement = $('.dropdown.inline');
this.$dropdownMenuElement = $('.dropdown-menu', this.dropdownContainerElement);
- this.projectsData = getJSONFixture('projects.json');
+ this.projectsData = getJSONFixture('static/projects.json');
});
afterEach(() => {
diff --git a/spec/javascripts/test_constants.js b/spec/javascripts/test_constants.js
index a820dd2d09c..24b5512b053 100644
--- a/spec/javascripts/test_constants.js
+++ b/spec/javascripts/test_constants.js
@@ -1,7 +1,7 @@
export const FIXTURES_PATH = '/base/spec/javascripts/fixtures';
export const TEST_HOST = 'http://test.host';
-export const DUMMY_IMAGE_URL = `${FIXTURES_PATH}/one_white_pixel.png`;
+export const DUMMY_IMAGE_URL = `${FIXTURES_PATH}/static/images/one_white_pixel.png`;
-export const GREEN_BOX_IMAGE_URL = `${FIXTURES_PATH}/images/green_box.png`;
-export const RED_BOX_IMAGE_URL = `${FIXTURES_PATH}/images/red_box.png`;
+export const GREEN_BOX_IMAGE_URL = `${FIXTURES_PATH}/static/images/green_box.png`;
+export const RED_BOX_IMAGE_URL = `${FIXTURES_PATH}/static/images/red_box.png`;
diff --git a/spec/javascripts/vue_shared/components/project_selector/project_list_item_spec.js b/spec/javascripts/vue_shared/components/project_selector/project_list_item_spec.js
index b95183747bb..268ced38f40 100644
--- a/spec/javascripts/vue_shared/components/project_selector/project_list_item_spec.js
+++ b/spec/javascripts/vue_shared/components/project_selector/project_list_item_spec.js
@@ -9,8 +9,8 @@ describe('ProjectListItem component', () => {
let wrapper;
let vm;
let options;
- loadJSONFixtures('projects.json');
- const project = getJSONFixture('projects.json')[0];
+ loadJSONFixtures('static/projects.json');
+ const project = getJSONFixture('static/projects.json')[0];
beforeEach(() => {
options = {
diff --git a/spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js b/spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js
index ba9ec8f2f19..34c0cd435cd 100644
--- a/spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js
+++ b/spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js
@@ -8,8 +8,8 @@ import { trimText } from 'spec/helpers/vue_component_helper';
describe('ProjectSelector component', () => {
let wrapper;
let vm;
- loadJSONFixtures('projects.json');
- const allProjects = getJSONFixture('projects.json');
+ loadJSONFixtures('static/projects.json');
+ const allProjects = getJSONFixture('static/projects.json');
const searchResults = allProjects.slice(0, 5);
let selected = [];
selected = selected.concat(allProjects.slice(0, 3)).concat(allProjects.slice(5, 8));
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 54369ff75f4..482e9c05da8 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -322,6 +322,7 @@ project:
- pool_repository
- kubernetes_namespaces
- error_tracking_setting
+- metrics_setting
award_emoji:
- awardable
- user
@@ -360,3 +361,5 @@ error_tracking_setting:
- project
suggestions:
- note
+metrics_setting:
+- project
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index ebb62124cb1..591a3d296c2 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -606,7 +606,6 @@ ResourceLabelEvent:
- user_id
- created_at
ErrorTracking::ProjectErrorTrackingSetting:
-- id
- api_url
- project_id
- project_name
@@ -626,3 +625,8 @@ MergeRequestAssignee:
- id
- user_id
- merge_request_id
+ProjectMetricsSetting:
+- project_id
+- external_dashboard_url
+- created_at
+- updated_at
diff --git a/spec/models/project_metrics_setting_spec.rb b/spec/models/project_metrics_setting_spec.rb
new file mode 100644
index 00000000000..7df01625ba1
--- /dev/null
+++ b/spec/models/project_metrics_setting_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ProjectMetricsSetting do
+ describe 'Associations' do
+ it { is_expected.to belong_to(:project) }
+ end
+
+ describe 'Validations' do
+ context 'when external_dashboard_url is over 255 chars' do
+ before do
+ subject.external_dashboard_url = 'https://' + 'a' * 250
+ end
+
+ it 'fails validation' do
+ expect(subject).not_to be_valid
+ expect(subject.errors.messages[:external_dashboard_url])
+ .to include('is too long (maximum is 255 characters)')
+ end
+ end
+
+ context 'with unsafe url' do
+ before do
+ subject.external_dashboard_url = %{https://replaceme.com/'><script>alert(document.cookie)</script>}
+ end
+
+ it { is_expected.to be_invalid }
+ end
+
+ context 'non ascii chars in external_dashboard_url' do
+ before do
+ subject.external_dashboard_url = 'http://gitlab.com/api/0/projects/project1/something€'
+ end
+
+ it { is_expected.to be_invalid }
+ end
+
+ context 'internal url in external_dashboard_url' do
+ before do
+ subject.external_dashboard_url = 'http://192.168.1.1'
+ end
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'external_dashboard_url is blank' do
+ before do
+ subject.external_dashboard_url = ''
+ end
+
+ it { is_expected.to be_invalid }
+ end
+ end
+end
diff --git a/spec/services/projects/operations/update_service_spec.rb b/spec/services/projects/operations/update_service_spec.rb
index 86b1ec83f50..7e765659b9d 100644
--- a/spec/services/projects/operations/update_service_spec.rb
+++ b/spec/services/projects/operations/update_service_spec.rb
@@ -11,6 +11,56 @@ describe Projects::Operations::UpdateService do
subject { described_class.new(project, user, params) }
describe '#execute' do
+ context 'metrics dashboard setting' do
+ let(:params) do
+ {
+ metrics_setting_attributes: {
+ external_dashboard_url: 'http://gitlab.com'
+ }
+ }
+ end
+
+ context 'without existing metrics dashboard setting' do
+ it 'creates a setting' do
+ expect(result[:status]).to eq(:success)
+
+ expect(project.reload.metrics_setting.external_dashboard_url).to eq(
+ 'http://gitlab.com'
+ )
+ end
+ end
+
+ context 'with existing metrics dashboard setting' do
+ before do
+ create(:project_metrics_setting, project: project)
+ end
+
+ it 'updates the settings' do
+ expect(result[:status]).to eq(:success)
+
+ expect(project.reload.metrics_setting.external_dashboard_url).to eq(
+ 'http://gitlab.com'
+ )
+ end
+
+ context 'with blank external_dashboard_url in params' do
+ let(:params) do
+ {
+ metrics_setting_attributes: {
+ external_dashboard_url: ''
+ }
+ }
+ end
+
+ it 'destroys the metrics_setting entry in DB' do
+ expect(result[:status]).to eq(:success)
+
+ expect(project.reload.metrics_setting).to be_nil
+ end
+ end
+ end
+ end
+
context 'error tracking' do
context 'with existing error tracking setting' do
let(:params) do