diff options
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 Binary files differindex cd1ff9f9ade..cd1ff9f9ade 100644 --- a/spec/javascripts/fixtures/images/green_box.png +++ b/spec/javascripts/fixtures/static/images/green_box.png diff --git a/spec/javascripts/fixtures/one_white_pixel.png b/spec/javascripts/fixtures/static/images/one_white_pixel.png Binary files differindex 073fcf40a18..073fcf40a18 100644 --- a/spec/javascripts/fixtures/one_white_pixel.png +++ b/spec/javascripts/fixtures/static/images/one_white_pixel.png diff --git a/spec/javascripts/fixtures/images/red_box.png b/spec/javascripts/fixtures/static/images/red_box.png Binary files differindex 73b2927da0f..73b2927da0f 100644 --- a/spec/javascripts/fixtures/images/red_box.png +++ b/spec/javascripts/fixtures/static/images/red_box.png 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 |