diff options
33 files changed, 430 insertions, 41 deletions
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml index 5bd19309528..6578eec8234 100644 --- a/.gitlab/ci/frontend.gitlab-ci.yml +++ b/.gitlab/ci/frontend.gitlab-ci.yml @@ -74,7 +74,6 @@ gitlab:assets:compile pull-cache: - .default-before_script - .assets-compile-cache - .only:changes-code-backstage-qa - - .use-pg9 stage: prepare script: - node --version @@ -83,6 +82,7 @@ gitlab:assets:compile pull-cache: - retry bundle exec rake gitlab:assets:compile - scripts/clean-old-cached-assets variables: + SETUP_DB: "false" # we override the max_old_space_size to prevent OOM errors NODE_OPTIONS: --max_old_space_size=3584 cache: diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js index 0d10c896a47..f1b481fc386 100644 --- a/app/assets/javascripts/boards/index.js +++ b/app/assets/javascripts/boards/index.js @@ -68,6 +68,8 @@ export default () => { Board, BoardSidebar, BoardAddIssuesModal, + BoardSettingsSidebar: () => + import('ee_component/boards/components/board_settings_sidebar.vue'), }, store, data: { diff --git a/app/assets/javascripts/boards/stores/state.js b/app/assets/javascripts/boards/stores/state.js index 24f44dc5629..731aea996fb 100644 --- a/app/assets/javascripts/boards/stores/state.js +++ b/app/assets/javascripts/boards/stores/state.js @@ -1,3 +1,4 @@ export default () => ({ isShowingLabels: true, + activeListId: 0, }); diff --git a/app/models/project.rb b/app/models/project.rb index bc8757ea888..cfdcdbed502 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -334,7 +334,7 @@ class Project < ApplicationRecord delegate :add_guest, :add_reporter, :add_developer, :add_maintainer, :add_role, to: :team delegate :add_master, to: :team # @deprecated delegate :group_runners_enabled, :group_runners_enabled=, :group_runners_enabled?, to: :ci_cd_settings - delegate :root_ancestor, to: :namespace, allow_nil: true + delegate :root_ancestor, :actual_limits, to: :namespace, allow_nil: true delegate :last_pipeline, to: :commit, allow_nil: true delegate :external_dashboard_url, to: :metrics_setting, allow_nil: true, prefix: true delegate :default_git_depth, :default_git_depth=, to: :ci_cd_settings, prefix: :ci diff --git a/app/models/project_services/asana_service.rb b/app/models/project_services/asana_service.rb index 757b2f17fb9..c4fcdcc05c5 100644 --- a/app/models/project_services/asana_service.rb +++ b/app/models/project_services/asana_service.rb @@ -24,7 +24,7 @@ get the commit comment added to it. You can also close a task with a message containing: `fix #123456`. You can create a Personal Access Token here: -http://app.asana.com/-/account_api' +https://app.asana.com/0/developer-console' end def self.to_param diff --git a/app/services/metrics/dashboard/pod_dashboard_service.rb b/app/services/metrics/dashboard/pod_dashboard_service.rb new file mode 100644 index 00000000000..16b87d2d587 --- /dev/null +++ b/app/services/metrics/dashboard/pod_dashboard_service.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +module Metrics + module Dashboard + class PodDashboardService < ::Metrics::Dashboard::PredefinedDashboardService + DASHBOARD_PATH = 'config/prometheus/pod_metrics.yml' + DASHBOARD_NAME = 'Pod Health' + end + end +end diff --git a/app/views/shared/boards/_show.html.haml b/app/views/shared/boards/_show.html.haml index 93fc839a371..7f62b983bfc 100644 --- a/app/views/shared/boards/_show.html.haml +++ b/app/views/shared/boards/_show.html.haml @@ -29,6 +29,7 @@ ":board-id" => "boardId", ":key" => "list.id" } = render "shared/boards/components/sidebar", group: group + = render_if_exists 'shared/boards/components/board_settings_sidebar' - if @project %board-add-issues-modal{ "new-issue-path" => new_project_issue_path(@project), "milestone-path" => milestones_filter_dropdown_path, diff --git a/changelogs/unreleased/36103-links-to-design-comments-from-todos-and-system-notes-do-not-jump-to.yml b/changelogs/unreleased/36103-links-to-design-comments-from-todos-and-system-notes-do-not-jump-to.yml new file mode 100644 index 00000000000..0c7941af93a --- /dev/null +++ b/changelogs/unreleased/36103-links-to-design-comments-from-todos-and-system-notes-do-not-jump-to.yml @@ -0,0 +1,5 @@ +--- +title: Links to design comments now lead to specific note +merge_request: 21724 +author: +type: fixed diff --git a/changelogs/unreleased/managed-cluster-applications-ci-template-ensure-namespace.yml b/changelogs/unreleased/managed-cluster-applications-ci-template-ensure-namespace.yml new file mode 100644 index 00000000000..edc79f76b87 --- /dev/null +++ b/changelogs/unreleased/managed-cluster-applications-ci-template-ensure-namespace.yml @@ -0,0 +1,5 @@ +--- +title: Ensure namespace is present for Managed-Cluster-Applications CI template +merge_request: 21903 +author: +type: fixed diff --git a/config/prometheus/pod_metrics.yml b/config/prometheus/pod_metrics.yml new file mode 100644 index 00000000000..29575ec543e --- /dev/null +++ b/config/prometheus/pod_metrics.yml @@ -0,0 +1,59 @@ +dashboard: 'Pod metrics' +priority: 10 +panel_groups: +- group: CPU metrics + panels: + - title: "CPU usage" + type: "line-chart" + y_label: "Cores per pod" + metrics: + - id: pod_cpu_usage_seconds_total + query_range: 'rate(container_cpu_usage_seconds_total{pod_name="{{pod_name}}",container_name="POD"}[5m])' + unit: "cores" + label: pod_name +- group: Memory metrics + panels: + - title: "Memory usage working set" + type: "line-chart" + y_label: "Working set memory (MiB)" + metrics: + - id: pod_memory_working_set + query_range: 'container_memory_working_set_bytes{pod_name="{{pod_name}}",container_name="POD"}/1024/1024' + unit: "MiB" + label: pod_name +- group: Network metrics + panels: + - title: "Network Receive (In)" + type: "line-chart" + y_label: "Received (KiB/sec)" + metrics: + - id: pod_network_receive + query_range: 'rate(container_network_receive_bytes_total{pod_name="{{pod_name}}",container_name="POD"}[5m])/1024' + unit: "KiB / sec" + label: pod_name + - title: "Network Transmit (Out)" + type: "line-chart" + y_label: "Transmitted (KiB/sec)" + metrics: + - id: pod_network_transmit + query_range: 'rate(container_network_transmit_bytes_total{pod_name="{{pod_name}}",container_name="POD"}[5m])/1024' + unit: "KiB / sec" + label: pod_name +- group: Disk metrics + panels: + - title: "Disk Reads" + type: "line-chart" + y_label: "Disk reads (KiB/sec)" + metrics: + - id: pod_disk_reads + query_range: 'rate(container_fs_reads_bytes_total{container_name="POD",pod_name="{{pod_name}}"}[5m])/1024' + unit: "KiB / sec" + label: pod_name + - title: "Disk Writes" + type: "line-chart" + y_label: "Disk writes (KiB/sec)" + metrics: + - id: pod_disk_writes + query_range: 'rate(container_fs_writes_bytes_total{container_name="POD",pod_name="{{pod_name}}"}[5m])/1024' + unit: "KiB / sec" + label: pod_name diff --git a/db/migrate/20191216094119_add_id_to_plan_limits.rb b/db/migrate/20191216094119_add_id_to_plan_limits.rb new file mode 100644 index 00000000000..05ebd900df3 --- /dev/null +++ b/db/migrate/20191216094119_add_id_to_plan_limits.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class AddIdToPlanLimits < ActiveRecord::Migration[5.2] + DOWNTIME = false + + def up + add_column(:plan_limits, :id, :primary_key) unless column_exists?(:plan_limits, :id) + end + + def down + remove_column(:plan_limits, :id) + end +end diff --git a/db/migrate/20191216183531_add_project_hooks_to_plan_limits.rb b/db/migrate/20191216183531_add_project_hooks_to_plan_limits.rb new file mode 100644 index 00000000000..c56b6edf029 --- /dev/null +++ b/db/migrate/20191216183531_add_project_hooks_to_plan_limits.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class AddProjectHooksToPlanLimits < ActiveRecord::Migration[5.2] + DOWNTIME = false + + def change + add_column(:plan_limits, :project_hooks, :integer, default: 0, null: false) + end +end diff --git a/db/migrate/20191216183532_insert_project_hooks_plan_limits.rb b/db/migrate/20191216183532_insert_project_hooks_plan_limits.rb new file mode 100644 index 00000000000..b2c0121dd24 --- /dev/null +++ b/db/migrate/20191216183532_insert_project_hooks_plan_limits.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +class InsertProjectHooksPlanLimits < ActiveRecord::Migration[5.2] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def up + return unless Gitlab.com? + + create_or_update_plan_limit('project_hooks', 'free', 10) + create_or_update_plan_limit('project_hooks', 'bronze', 20) + create_or_update_plan_limit('project_hooks', 'silver', 30) + create_or_update_plan_limit('project_hooks', 'gold', 100) + end + + def down + return unless Gitlab.com? + + create_or_update_plan_limit('project_hooks', 'free', 0) + create_or_update_plan_limit('project_hooks', 'bronze', 0) + create_or_update_plan_limit('project_hooks', 'silver', 0) + create_or_update_plan_limit('project_hooks', 'gold', 0) + end +end diff --git a/db/schema.rb b/db/schema.rb index 7b0ecce825c..d3e9f66c388 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: 2019_12_14_175727) do +ActiveRecord::Schema.define(version: 2019_12_16_183532) do # These are extensions that must be enabled in order to support this database enable_extension "pg_trgm" @@ -2987,6 +2987,7 @@ ActiveRecord::Schema.define(version: 2019_12_14_175727) do t.integer "ci_active_pipelines", default: 0, null: false t.integer "ci_pipeline_size", default: 0, null: false t.integer "ci_active_jobs", default: 0, null: false + t.integer "project_hooks", default: 0, null: false t.index ["plan_id"], name: "index_plan_limits_on_plan_id", unique: true end diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md index c544c531d9f..9218ffa4006 100644 --- a/doc/administration/gitaly/index.md +++ b/doc/administration/gitaly/index.md @@ -719,6 +719,105 @@ result as you did in the beginning: Note that `enforced="true"`, meaning that authentication is being enforced. +## Direct Git access in GitLab Rails + +Also known as "the Rugged patches". + +### History + +Before Gitaly existed, the things that are now Gitaly clients used to +access Git repositories directly. Either on a local disk in the case of +e.g. a single-machine Omnibus GitLab installation, or via NFS in the +case of a horizontally scaled GitLab installation. + +Besides running plain `git` commands, in GitLab Rails we also used to +use a Ruby gem (library) called +[Rugged](https://github.com/libgit2/rugged). Rugged is a wrapper around +[libgit2](https://libgit2.org/), a stand-alone implementation of Git in +the form of a C library. + +Over time it has become clear to use that Rugged, and particularly +Rugged in combination with the [Unicorn](https://bogomips.org/unicorn/) +web server, is extremely efficient. Because libgit2 is a *library* and +not an external process, there was very little overhead between GitLab +application code that tried to look up data in Git repositories, and the +Git implementation itself. + +Because Rugged+Unicorn was so efficient, GitLab's application code ended +up with lots of duplicate Git object lookups (like looking up the +`master` commmit a dozen times in one request). We could write +inefficient code without being punished for it. + +When we migrated these Git lookups to Gitaly calls, we were suddenly +getting a much higher fixed cost per Git lookup. Even when Gitaly is +able to re-use an already-running `git` process to look up e.g. a commit +you still have the cost of a network roundtrip to Gitaly, and within +Gitaly a write/read roundtrip on the Unix pipes that connect Gitaly to +the `git` process. + +Using GitLab.com performance as our yardstick, we pushed down the number +of Gitaly calls per request until the loss of Rugged's efficiency was no +longer felt. It also helped that we run Gitaly itself directly on the +Git file severs, rather than via NFS mounts: this gave us a speed boost +that counteracted the negative effect of not using Rugged anymore. + +Unfortunately, some *other* deployments of GitLab could not ditch NFS +like we did on GitLab.com and they got the worst of both worlds: the +slowness of NFS and the increased inherent overhead of Gitaly. + +As a performance band-aid for these stuck-on-NFS deployments, we +re-introduced some of the old Rugged code that got deleted from +GitLab Rails during the Gitaly migration project. These pieces of +re-introduced code are informally referred to as "the Rugged patches". + +### Activation of direct Git access in GitLab Rails + +The Ruby methods that perform direct Git access are hidden behind [feature +flags](../../development/gitaly.md#legacy-rugged-code). These feature +flags are off by default. It is not good if you need to know about +feature flags to get the best performance so in a second iteration, we +added an automatic mechanism that will enable direct Git access. + +When GitLab Rails calls a function that has a Rugged patch it performs +two checks. The result of both of these checks is cached. + +1. Is the feature flag for this patch set in the database? If so, do + what the feature flag says. +1. If the feature flag is not set (i.e. neither true nor false), try to + see if we can access filesystem underneath the Gitaly server + directly. If so, use the Rugged patch. + +To see if GitLab Rails can access the repo filesystem directly, we use +the following heuristic: + +- Gitaly ensures that the filesystem has a metadata file in its root + with a UUID in it. +- Gitaly reports this UUID to GitLab Rails via the `ServerInfo` RPC. +- GitLab Rails tries to read the metadata file directly. If it exists, + and if the UUID's match, assume we have direct access. + +Because of the way the UUID check works, and because Omnibus GitLab will +fill in the correct repository paths in the GitLab Rails config file +`config/gitlab.yml`, **direct Git access in GitLab Rails is on by default in +Omnibus**. + +### Plans to remove direct Git access in GitLab Rails + +For the sake of removing complexity it is desirable that we get rid of +direct Git access in GitLab Rails. For as long as some GitLab installations are stuck +with Git repositories on slow NFS, however, we cannot just remove them. + +There are two prongs to our efforts to remove direct Git access in GitLab Rails: + +1. Reduce the number of (inefficient) Gitaly queries made by + GitLab Rails. +1. Persuade everybody who runs a Highly Available / horizontally scaled + GitLab installation to move off of NFS. + +The second prong is the only real solution. For this we need [Gitaly +HA](https://gitlab.com/groups/gitlab-org/-/epics?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=Gitaly%20HA), +which is still under development as of December 2019. + ## Troubleshooting Gitaly ### Checking versions when using standalone Gitaly nodes diff --git a/doc/policy/maintenance.md b/doc/policy/maintenance.md index eb1193a50bd..7617d0c8881 100644 --- a/doc/policy/maintenance.md +++ b/doc/policy/maintenance.md @@ -142,7 +142,6 @@ that could change behavior in the next major release. To ensure background migrations are successful, increment by one minor version during the version jump before installing newer releases. For example: `11.11.x` -> `12.0.x` - Please see the table below for some examples: | Latest stable version | Your version | Recommended upgrade path | Note | @@ -152,6 +151,9 @@ Please see the table below for some examples: | 11.3.4 | 8.13.4 | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7` is the last version in version `8`, `9.5.10` is the last version in version `9`, `10.8.7` is the last version in version `10` | | 12.5.8 | 11.3.4 | `11.3.4` -> `11.11.8` -> `12.0.9` -> `12.5.8` | `11.11.8` is the last version in version `11` | +To check the size of `background_migration` queue and to learn more about background migrations +see [Upgrading without downtime](../update/README.md#upgrading-without-downtime). + More information about the release procedures can be found in our [release documentation](https://gitlab.com/gitlab-org/release/docs). You may also want to read our [Responsible Disclosure Policy](https://about.gitlab.com/security/disclosure/). diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md index f371f2ac288..bb946574371 100644 --- a/doc/user/project/integrations/webhooks.md +++ b/doc/user/project/integrations/webhooks.md @@ -47,6 +47,20 @@ and **per project and per group** for **GitLab Enterprise Edition**. Navigate to the webhooks page by going to your project's **Settings ➔ Integrations**. +## Maximum number of webhooks (per tier) + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/merge_requests/20730) in GitLab 12.6. + +A maximum number of project webhooks applies to each [GitLab.com +tier](https://about.gitlab.com/pricing/), as shown in the following table: + +| Tier | Number of webhooks per project | +|----------|--------------------------------| +| Free | 10 | +| Bronze | 20 | +| Silver | 30 | +| Gold | 100 | + ## Use-cases - You can set up a webhook in GitLab to send a notification to diff --git a/doc/user/project/operations/error_tracking.md b/doc/user/project/operations/error_tracking.md index 230e388d497..912d7fdbef5 100644 --- a/doc/user/project/operations/error_tracking.md +++ b/doc/user/project/operations/error_tracking.md @@ -42,9 +42,9 @@ NOTE: **Note:** You will need at least Reporter [permissions](../../permissions.md) to view the Error Tracking list. The Error Tracking list may be found at **Operations > Error Tracking** in your project's sidebar. -Errors can be filtered by title. +Errors can be filtered by title or sorted by Frequency, First Seen or Last Seen. Errors are always sorted in descending order by the field specified. -![Error Tracking list](img/error_tracking_list.png) +![Error Tracking list](img/error_tracking_list_v12_6.png) ## Error Details diff --git a/doc/user/project/operations/img/error_tracking_list.png b/doc/user/project/operations/img/error_tracking_list.png Binary files differdeleted file mode 100644 index 79b464e021e..00000000000 --- a/doc/user/project/operations/img/error_tracking_list.png +++ /dev/null diff --git a/doc/user/project/operations/img/error_tracking_list_v12_6.png b/doc/user/project/operations/img/error_tracking_list_v12_6.png Binary files differnew file mode 100644 index 00000000000..b99c83c14d3 --- /dev/null +++ b/doc/user/project/operations/img/error_tracking_list_v12_6.png diff --git a/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml index 8f50f38bbed..1708984c1cb 100644 --- a/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml @@ -7,7 +7,7 @@ code_quality: variables: DOCKER_DRIVER: overlay2 DOCKER_TLS_CERTDIR: "" - CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/security-products/codequality:12-5-stable" + CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/security-products/codequality:0.85.5" script: - | if ! docker info &>/dev/null; then diff --git a/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml b/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml index 938b6f89b76..9a5b0f79ecf 100644 --- a/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml @@ -9,6 +9,7 @@ apply: INGRESS_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/ingress/values.yaml SENTRY_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/sentry/values.yaml script: + - kubectl get namespace "$TILLER_NAMESPACE" || kubectl create namespace "$TILLER_NAMESPACE" - gitlab-managed-apps /usr/local/share/gitlab-managed-apps/helmfile.yaml only: refs: diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb index 03bde611451..f9340b262e5 100644 --- a/lib/gitlab/database/migration_helpers.rb +++ b/lib/gitlab/database/migration_helpers.rb @@ -1052,6 +1052,15 @@ into similar problems in the future (e.g. when new tables are created). connection.select_value(index_sql).to_i > 0 end + def create_or_update_plan_limit(limit_name, plan_name, limit_value) + execute <<~SQL + INSERT INTO plan_limits (plan_id, #{quote_column_name(limit_name)}) + VALUES + ((SELECT id FROM plans WHERE name = #{quote(plan_name)} LIMIT 1), #{quote(limit_value)}) + ON CONFLICT (plan_id) DO UPDATE SET #{quote_column_name(limit_name)} = EXCLUDED.#{quote_column_name(limit_name)}; + SQL + end + private def tables_match?(target_table, foreign_key_table) diff --git a/lib/gitlab/metrics/dashboard/service_selector.rb b/lib/gitlab/metrics/dashboard/service_selector.rb index 22314c2a0ee..5b6f25420e0 100644 --- a/lib/gitlab/metrics/dashboard/service_selector.rb +++ b/lib/gitlab/metrics/dashboard/service_selector.rb @@ -22,6 +22,7 @@ module Gitlab return SERVICES::DynamicEmbedService if dynamic_embed?(params) return SERVICES::DefaultEmbedService if params[:embedded] return SERVICES::SystemDashboardService if system_dashboard?(params[:dashboard_path]) + return SERVICES::PodDashboardService if pod_dashboard?(params[:dashboard_path]) return SERVICES::ProjectDashboardService if params[:dashboard_path] default_service @@ -37,6 +38,10 @@ module Gitlab SERVICES::SystemDashboardService.matching_dashboard?(filepath) end + def pod_dashboard?(filepath) + SERVICES::PodDashboardService.matching_dashboard?(filepath) + end + def custom_metric_embed?(params) SERVICES::CustomMetricEmbedService.valid_params?(params) end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index d0cb07b3859..9fe8e8e670b 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -10223,6 +10223,9 @@ msgstr "" msgid "Label" msgstr "" +msgid "Label List" +msgstr "" + msgid "Label actions dropdown" msgstr "" @@ -10982,6 +10985,9 @@ msgstr "" msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}." msgstr "" +msgid "Maximum number of %{name} (%{count}) exceeded" +msgstr "" + msgid "Maximum number of comments exceeded" msgstr "" @@ -18887,6 +18893,12 @@ msgstr "" msgid "Too many changes to show." msgstr "" +msgid "Too many namespaces enabled. You will need to manage them via the console or the API." +msgstr "" + +msgid "Too many projects enabled. You will need to manage them via the console or the API." +msgstr "" + msgid "Topics" msgstr "" diff --git a/rubocop/cop/migration/add_column.rb b/rubocop/cop/migration/add_column.rb index 2530d6477e8..a25bd843559 100644 --- a/rubocop/cop/migration/add_column.rb +++ b/rubocop/cop/migration/add_column.rb @@ -8,7 +8,10 @@ module RuboCop class AddColumn < RuboCop::Cop::Cop include MigrationHelpers - WHITELISTED_TABLES = [:application_settings].freeze + WHITELISTED_TABLES = %i[ + application_settings + plan_limits + ].freeze MSG = '`add_column` with a default value requires downtime, ' \ 'use `add_column_with_default` instead'.freeze diff --git a/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/panel_groups.json b/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/panel_groups.json index d7a390adcdc..f4afb4cbffc 100644 --- a/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/panel_groups.json +++ b/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/panel_groups.json @@ -2,7 +2,6 @@ "type": "object", "required": [ "group", - "priority", "panels" ], "properties": { diff --git a/spec/frontend/lib/utils/url_utility_spec.js b/spec/frontend/lib/utils/url_utility_spec.js index a625c9cd274..048736d75f6 100644 --- a/spec/frontend/lib/utils/url_utility_spec.js +++ b/spec/frontend/lib/utils/url_utility_spec.js @@ -330,46 +330,46 @@ describe('URL utility', () => { expect(urlUtils.escapeFileUrl('foo/bar/file.md')).toBe('foo/bar/file.md'); }); }); -}); -describe('setUrlParams', () => { - it('adds new params as query string', () => { - const url = 'https://gitlab.com/test'; + describe('setUrlParams', () => { + it('adds new params as query string', () => { + const url = 'https://gitlab.com/test'; - expect( - urlUtils.setUrlParams({ group_id: 'gitlab-org', project_id: 'my-project' }, url), - ).toEqual('https://gitlab.com/test?group_id=gitlab-org&project_id=my-project'); - }); + expect( + urlUtils.setUrlParams({ group_id: 'gitlab-org', project_id: 'my-project' }, url), + ).toEqual('https://gitlab.com/test?group_id=gitlab-org&project_id=my-project'); + }); - it('updates an existing parameter', () => { - const url = 'https://gitlab.com/test?group_id=gitlab-org&project_id=my-project'; + it('updates an existing parameter', () => { + const url = 'https://gitlab.com/test?group_id=gitlab-org&project_id=my-project'; - expect(urlUtils.setUrlParams({ project_id: 'gitlab-test' }, url)).toEqual( - 'https://gitlab.com/test?group_id=gitlab-org&project_id=gitlab-test', - ); - }); + expect(urlUtils.setUrlParams({ project_id: 'gitlab-test' }, url)).toEqual( + 'https://gitlab.com/test?group_id=gitlab-org&project_id=gitlab-test', + ); + }); - it("removes the project_id param when it's value is null", () => { - const url = 'https://gitlab.com/test?group_id=gitlab-org&project_id=my-project'; + it("removes the project_id param when it's value is null", () => { + const url = 'https://gitlab.com/test?group_id=gitlab-org&project_id=my-project'; - expect(urlUtils.setUrlParams({ project_id: null }, url)).toEqual( - 'https://gitlab.com/test?group_id=gitlab-org', - ); - }); + expect(urlUtils.setUrlParams({ project_id: null }, url)).toEqual( + 'https://gitlab.com/test?group_id=gitlab-org', + ); + }); - it('handles arrays properly', () => { - const url = 'https://gitlab.com/test'; + it('handles arrays properly', () => { + const url = 'https://gitlab.com/test'; - expect(urlUtils.setUrlParams({ label_name: ['foo', 'bar'] }, url)).toEqual( - 'https://gitlab.com/test?label_name=foo&label_name=bar', - ); - }); + expect(urlUtils.setUrlParams({ label_name: ['foo', 'bar'] }, url)).toEqual( + 'https://gitlab.com/test?label_name=foo&label_name=bar', + ); + }); - it('removes all existing URL params and sets a new param when cleanParams=true', () => { - const url = 'https://gitlab.com/test?group_id=gitlab-org&project_id=my-project'; + it('removes all existing URL params and sets a new param when cleanParams=true', () => { + const url = 'https://gitlab.com/test?group_id=gitlab-org&project_id=my-project'; - expect(urlUtils.setUrlParams({ foo: 'bar' }, url, true)).toEqual( - 'https://gitlab.com/test?foo=bar', - ); + expect(urlUtils.setUrlParams({ foo: 'bar' }, url, true)).toEqual( + 'https://gitlab.com/test?foo=bar', + ); + }); }); }); diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb index 2ba253f9652..cac6908f4b4 100644 --- a/spec/lib/gitlab/database/migration_helpers_spec.rb +++ b/spec/lib/gitlab/database/migration_helpers_spec.rb @@ -1440,4 +1440,17 @@ describe Gitlab::Database::MigrationHelpers do end end end + + describe '#create_or_update_plan_limit' do + it 'creates or updates plan limits' do + expect(model).to receive(:execute).with <<~SQL + INSERT INTO plan_limits (plan_id, "project_hooks") + VALUES + ((SELECT id FROM plans WHERE name = 'free' LIMIT 1), '10') + ON CONFLICT (plan_id) DO UPDATE SET "project_hooks" = EXCLUDED."project_hooks"; + SQL + + model.create_or_update_plan_limit('project_hooks', 'free', 10) + end + end end diff --git a/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb b/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb index 0d4562f78f1..e0c8133994b 100644 --- a/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb +++ b/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb @@ -22,6 +22,12 @@ describe Gitlab::Metrics::Dashboard::ServiceSelector do it { is_expected.to be Metrics::Dashboard::SystemDashboardService } end + + context 'when the path is for the pod dashboard' do + let(:arguments) { { dashboard_path: pod_dashboard_path } } + + it { is_expected.to be Metrics::Dashboard::PodDashboardService } + end end context 'when the embedded flag is provided' do diff --git a/spec/migrations/insert_project_hooks_plan_limits_spec.rb b/spec/migrations/insert_project_hooks_plan_limits_spec.rb new file mode 100644 index 00000000000..abc2ccd0507 --- /dev/null +++ b/spec/migrations/insert_project_hooks_plan_limits_spec.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +require 'spec_helper' +require Rails.root.join('db', 'migrate', '20191216183532_insert_project_hooks_plan_limits.rb') + +describe InsertProjectHooksPlanLimits, :migration do + let(:migration) { described_class.new } + let(:plans) { table(:plans) } + let(:plan_limits) { table(:plan_limits) } + + before do + plans.create(id: 34, name: 'free') + plans.create(id: 2, name: 'bronze') + plans.create(id: 3, name: 'silver') + plans.create(id: 4, name: 'gold') + plan_limits.create(plan_id: 34, ci_active_jobs: 5) + end + + context 'when on Gitlab.com' do + before do + expect(Gitlab).to receive(:com?).at_most(:twice).and_return(true) + end + + describe '#up' do + it 'updates the project_hooks plan limits' do + migration.up + + expect(plan_limits.pluck(:plan_id, :project_hooks, :ci_active_jobs)) + .to match_array([[34, 10, 5], [2, 20, 0], [3, 30, 0], [4, 100, 0]]) + end + end + + describe '#down' do + it 'updates the project_hooks plan limits to 0' do + migration.up + migration.down + + expect(plan_limits.pluck(:plan_id, :project_hooks, :ci_active_jobs)) + .to match_array([[34, 0, 5], [2, 0, 0], [3, 0, 0], [4, 0, 0]]) + end + end + end + + context 'when on self-hosted' do + before do + expect(Gitlab).to receive(:com?).and_return(false) + end + + describe '#up' do + it 'does not update the plan limits' do + migration.up + + expect(plan_limits.pluck(:plan_id, :project_hooks, :ci_active_jobs)) + .to match_array([[34, 0, 5]]) + end + end + + describe '#down' do + it 'does not update the plan limits' do + migration.down + + expect(plan_limits.pluck(:plan_id, :project_hooks, :ci_active_jobs)) + .to match_array([[34, 0, 5]]) + end + end + end +end diff --git a/spec/services/metrics/dashboard/pod_dashboard_service_spec.rb b/spec/services/metrics/dashboard/pod_dashboard_service_spec.rb new file mode 100644 index 00000000000..c3993bf71ea --- /dev/null +++ b/spec/services/metrics/dashboard/pod_dashboard_service_spec.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Metrics::Dashboard::PodDashboardService, :use_clean_rails_memory_store_caching do + include MetricsDashboardHelpers + + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project) } + let_it_be(:environment) { create(:environment, project: project) } + + before do + project.add_maintainer(user) + end + + describe 'get_dashboard' do + let(:dashboard_path) { described_class::DASHBOARD_PATH } + let(:service_params) { [project, user, { environment: environment, dashboard_path: dashboard_path }] } + let(:service_call) { described_class.new(*service_params).get_dashboard } + + it_behaves_like 'valid dashboard service response' + it_behaves_like 'caches the unprocessed dashboard for subsequent calls' + end +end diff --git a/spec/support/helpers/metrics_dashboard_helpers.rb b/spec/support/helpers/metrics_dashboard_helpers.rb index 98f235bdac4..5b425d0964d 100644 --- a/spec/support/helpers/metrics_dashboard_helpers.rb +++ b/spec/support/helpers/metrics_dashboard_helpers.rb @@ -22,6 +22,10 @@ module MetricsDashboardHelpers Metrics::Dashboard::SystemDashboardService::DASHBOARD_PATH end + def pod_dashboard_path + Metrics::Dashboard::PodDashboardService::DASHBOARD_PATH + end + def business_metric_title PrometheusMetricEnums.group_details[:business][:group_title] end |