diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-04-10 09:09:39 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-04-10 09:09:39 +0000 |
commit | c52b81f45762cb7f05a950689dfc6d51b197ea73 (patch) | |
tree | c44830c2fc21d13b81814958c44b09fa8d11c805 | |
parent | 187ee320b39af22929d74c5a2d9b0650bf50a09b (diff) | |
download | gitlab-ce-c52b81f45762cb7f05a950689dfc6d51b197ea73.tar.gz |
Add latest changes from gitlab-org/gitlab@master
21 files changed, 307 insertions, 111 deletions
diff --git a/.gitlab/ci/reports.gitlab-ci.yml b/.gitlab/ci/reports.gitlab-ci.yml index b1343afdb5e..61915aa798e 100644 --- a/.gitlab/ci/reports.gitlab-ci.yml +++ b/.gitlab/ci/reports.gitlab-ci.yml @@ -43,16 +43,16 @@ code_quality: # We need to duplicate this job's definition because it seems it's impossible to # override an included `only.refs`. # See https://gitlab.com/gitlab-org/gitlab/issues/31371. -# Once https://gitlab.com/gitlab-org/gitlab/merge_requests/16487 will be deployed -# to GitLab.com, we should be able to use the template and set SAST_DISABLE_DIND: "true". -sast: +.sast: extends: - .default-retry - .reports:rules:sast - .use-docker-in-docker stage: test - allow_failure: true + # `needs: []` starts the job immediately in the pipeline + # https://docs.gitlab.com/ee/ci/yaml/README.html#needs needs: [] + allow_failure: true artifacts: paths: - gl-sast-report.json # GitLab-specific @@ -63,22 +63,39 @@ sast: # emptying DOCKER_HOST so it can be detected properly on kubernetes executor # with the script below DOCKER_HOST: "" + DOCKER_DRIVER: overlay2 + DOCKER_TLS_CERTDIR: "" + SAST_ANALYZER_IMAGE_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers" + SAST_ANALYZER_IMAGE_TAG: 2 SAST_BRAKEMAN_LEVEL: 2 # GitLab-specific SAST_EXCLUDED_PATHS: qa,spec,doc,ee/spec # GitLab-specific script: - - export SAST_VERSION=${SP_VERSION:-$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')} - - | - if ! docker info &>/dev/null; then - if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then - export DOCKER_HOST='tcp://localhost:2375' - fi - fi - - | - ENVS=`printenv | grep -vE '^(DOCKER_|CI|GITLAB_|FF_|HOME|PWD|OLDPWD|PATH|SHLVL|HOSTNAME)' | sed -n '/^[^\t]/s/=.*//p' | sed '/^$/d' | sed 's/^/-e /g' | tr '\n' ' '` - docker run "$ENVS" \ - --volume "$PWD:/code" \ - --volume /var/run/docker.sock:/var/run/docker.sock \ - "registry.gitlab.com/gitlab-org/security-products/sast:$SAST_VERSION" /app/bin/run /code + - /analyzer run + +brakeman-sast: + extends: .sast + image: + name: "$SAST_ANALYZER_IMAGE_PREFIX/brakeman:$SAST_ANALYZER_IMAGE_TAG" + +eslint-sast: + extends: .sast + image: + name: "$SAST_ANALYZER_IMAGE_PREFIX/eslint:$SAST_ANALYZER_IMAGE_TAG" + +kubesec-sast: + extends: .sast + image: + name: "$SAST_ANALYZER_IMAGE_PREFIX/kubesec:$SAST_ANALYZER_IMAGE_TAG" + +nodejs-scan-sast: + extends: .sast + image: + name: "$SAST_ANALYZER_IMAGE_PREFIX/nodejs-scan:$SAST_ANALYZER_IMAGE_TAG" + +secrets-sast: + extends: .sast + image: + name: "$SAST_ANALYZER_IMAGE_PREFIX/secrets:$SAST_ANALYZER_IMAGE_TAG" # We need to duplicate this job's definition because it seems it's impossible to # override an included `only.refs`. diff --git a/app/assets/javascripts/monitoring/components/charts/annotations.js b/app/assets/javascripts/monitoring/components/charts/annotations.js index b0c89d5e374..de2b0c69a88 100644 --- a/app/assets/javascripts/monitoring/components/charts/annotations.js +++ b/app/assets/javascripts/monitoring/components/charts/annotations.js @@ -87,11 +87,17 @@ export const generateAnnotationsSeries = ({ deployments = [], annotations = [] } return { name: 'deployments', value: [deployment.createdAt, annotationsYAxisCoords.pos], + // style options symbol: deployment.icon, symbolSize: symbolSizes.default, itemStyle: { color: deployment.color, }, + // metadata that are accessible in `formatTooltipText` method + tooltipData: { + sha: deployment.sha.substring(0, 8), + commitUrl: deployment.commitUrl, + }, }; }); @@ -100,8 +106,12 @@ export const generateAnnotationsSeries = ({ deployments = [], annotations = [] } return { name: 'annotations', value: [annotation.from, annotationsYAxisCoords.pos], + // style options symbol: 'none', - description: annotation.description, + // metadata that are accessible in `formatTooltipText` method + tooltipData: { + description: annotation.description, + }, }; }); diff --git a/app/assets/javascripts/monitoring/components/charts/time_series.vue b/app/assets/javascripts/monitoring/components/charts/time_series.vue index f4cd6bbbb34..24aa8480ce4 100644 --- a/app/assets/javascripts/monitoring/components/charts/time_series.vue +++ b/app/assets/javascripts/monitoring/components/charts/time_series.vue @@ -262,19 +262,17 @@ export default { params.seriesData.forEach(dataPoint => { if (dataPoint.value) { - const [xVal, yVal] = dataPoint.value; + const [, yVal] = dataPoint.value; this.tooltip.type = dataPoint.name; if (this.isTooltipOfType(this.tooltip.type, this.$options.tooltipTypes.deployments)) { - const [deploy] = this.recentDeployments.filter( - deployment => deployment.createdAt === xVal, - ); - this.tooltip.sha = deploy.sha.substring(0, 8); - this.tooltip.commitUrl = deploy.commitUrl; + const { data = {} } = dataPoint; + this.tooltip.sha = data?.tooltipData?.sha; + this.tooltip.commitUrl = data?.tooltipData?.commitUrl; } else if ( this.isTooltipOfType(this.tooltip.type, this.$options.tooltipTypes.annotations) ) { const { data } = dataPoint; - this.tooltip.content.push(data?.description); + this.tooltip.content.push(data?.tooltipData?.description); } else { const { seriesName, color, dataIndex } = dataPoint; diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index ddda2de38cb..1131248dd3f 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -210,3 +210,15 @@ } } } + +.health-status { + .dropdown-body { + .health-divider { + border-top-color: $gray-200; + } + + .dropdown-item:not(.health-dropdown-item) { + padding: 0; + } + } +} diff --git a/app/presenters/projects/prometheus/alert_presenter.rb b/app/presenters/projects/prometheus/alert_presenter.rb index 02e22f8f46a..c03925c0871 100644 --- a/app/presenters/projects/prometheus/alert_presenter.rb +++ b/app/presenters/projects/prometheus/alert_presenter.rb @@ -3,7 +3,7 @@ module Projects module Prometheus class AlertPresenter < Gitlab::View::Presenter::Delegated - RESERVED_ANNOTATIONS = %w(gitlab_incident_markdown title).freeze + RESERVED_ANNOTATIONS = %w(gitlab_incident_markdown gitlab_y_label title).freeze GENERIC_ALERT_SUMMARY_ANNOTATIONS = %w(monitoring_tool service hosts).freeze MARKDOWN_LINE_BREAK = " \n".freeze INCIDENT_LABEL_NAME = IncidentManagement::CreateIssueService::INCIDENT_LABEL[:title].freeze diff --git a/app/services/metrics/dashboard/custom_metric_embed_service.rb b/app/services/metrics/dashboard/custom_metric_embed_service.rb index 456074ae6ad..22b592c7aa5 100644 --- a/app/services/metrics/dashboard/custom_metric_embed_service.rb +++ b/app/services/metrics/dashboard/custom_metric_embed_service.rb @@ -57,7 +57,7 @@ module Metrics # @return [Hash] override :raw_dashboard def raw_dashboard - panels_not_found!(identifiers) if panels.empty? + panels_not_found!(identifiers) if metrics.empty? { 'panel_groups' => [{ 'panels' => panels }] } end @@ -66,11 +66,20 @@ module Metrics # Generated dashboard panels for each metric which # matches the provided input. + # + # As the panel is generated + # on the fly, we're using default values for info + # not represented in the DB. + # # @return [Array<Hash>] def panels - strong_memoize(:panels) do - metrics.map { |metric| panel_for_metric(metric) } - end + [{ + type: DEFAULT_PANEL_TYPE, + weight: DEFAULT_PANEL_WEIGHT, + title: title, + y_label: y_label, + metrics: metrics.map(&:to_metric_hash) + }] end # Metrics which match the provided inputs. @@ -78,12 +87,14 @@ module Metrics # displayed in a single panel/chart. # @return [ActiveRecord::AssociationRelation<PromtheusMetric>] def metrics - PrometheusMetricsFinder.new( - project: project, - group: group_key, - title: title, - y_label: y_label - ).execute + strong_memoize(:metrics) do + PrometheusMetricsFinder.new( + project: project, + group: group_key, + title: title, + y_label: y_label + ).execute + end end # Returns a symbol representing the group that @@ -101,22 +112,6 @@ module Metrics .to_s end end - - # Returns a representation of a PromtheusMetric - # as a dashboard panel. As the panel is generated - # on the fly, we're using default values for info - # not represented in the DB. - # - # @return [Hash] - def panel_for_metric(metric) - { - type: DEFAULT_PANEL_TYPE, - weight: DEFAULT_PANEL_WEIGHT, - title: metric.title, - y_label: metric.y_label, - metrics: [metric.to_metric_hash] - } - end end end end diff --git a/changelogs/unreleased/sy-fix-multi-metric-embed.yml b/changelogs/unreleased/sy-fix-multi-metric-embed.yml new file mode 100644 index 00000000000..26fbac61c69 --- /dev/null +++ b/changelogs/unreleased/sy-fix-multi-metric-embed.yml @@ -0,0 +1,5 @@ +--- +title: Show multimetric embeds on a single chart +merge_request: 28841 +author: +type: fixed diff --git a/db/migrate/20200318183553_create_pypi_package_metadata.rb b/db/migrate/20200318183553_create_pypi_package_metadata.rb new file mode 100644 index 00000000000..3f0204d51ac --- /dev/null +++ b/db/migrate/20200318183553_create_pypi_package_metadata.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class CreatePypiPackageMetadata < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def change + create_table :packages_pypi_metadata, id: false do |t| + t.references :package, primary_key: true, index: false, default: nil, foreign_key: { to_table: :packages_packages, on_delete: :cascade }, type: :bigint + t.string "required_python", null: false, limit: 50 + end + end +end diff --git a/db/structure.sql b/db/structure.sql index 3faa5499f6c..d45ad4f739c 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -4493,6 +4493,11 @@ CREATE SEQUENCE public.packages_packages_id_seq ALTER SEQUENCE public.packages_packages_id_seq OWNED BY public.packages_packages.id; +CREATE TABLE public.packages_pypi_metadata ( + package_id bigint NOT NULL, + required_python character varying(50) NOT NULL +); + CREATE TABLE public.packages_tags ( id bigint NOT NULL, package_id integer NOT NULL, @@ -8146,6 +8151,9 @@ ALTER TABLE ONLY public.packages_package_files ALTER TABLE ONLY public.packages_packages ADD CONSTRAINT packages_packages_pkey PRIMARY KEY (id); +ALTER TABLE ONLY public.packages_pypi_metadata + ADD CONSTRAINT packages_pypi_metadata_pkey PRIMARY KEY (package_id); + ALTER TABLE ONLY public.packages_tags ADD CONSTRAINT packages_tags_pkey PRIMARY KEY (id); @@ -11596,6 +11604,9 @@ ALTER TABLE ONLY public.board_labels ALTER TABLE ONLY public.scim_identities ADD CONSTRAINT fk_rails_9421a0bffb FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +ALTER TABLE ONLY public.packages_pypi_metadata + ADD CONSTRAINT fk_rails_9698717cdd FOREIGN KEY (package_id) REFERENCES public.packages_packages(id) ON DELETE CASCADE; + ALTER TABLE ONLY public.packages_dependency_links ADD CONSTRAINT fk_rails_96ef1c00d3 FOREIGN KEY (package_id) REFERENCES public.packages_packages(id) ON DELETE CASCADE; @@ -13032,6 +13043,7 @@ COPY "schema_migrations" (version) FROM STDIN; 20200318164448 20200318165448 20200318175008 +20200318183553 20200319071702 20200319123041 20200319124127 diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql index 583e27f3301..402415b985c 100644 --- a/doc/api/graphql/reference/gitlab_schema.graphql +++ b/doc/api/graphql/reference/gitlab_schema.graphql @@ -468,6 +468,11 @@ input CreateEpicInput { clientMutationId: String """ + Indicates if the epic is confidential. Will be ignored if `confidential_epics` feature flag is disabled + """ + confidential: Boolean + + """ The description of the epic """ description: String @@ -2015,6 +2020,11 @@ type Epic implements Noteable { closedAt: Time """ + Indicates if the epic is confidential + """ + confidential: Boolean + + """ Timestamp of the epic's creation """ createdAt: Time @@ -8904,6 +8914,11 @@ input UpdateEpicInput { clientMutationId: String """ + Indicates if the epic is confidential. Will be ignored if `confidential_epics` feature flag is disabled + """ + confidential: Boolean + + """ The description of the epic """ description: String diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json index 79d4088e566..c214d7c3299 100644 --- a/doc/api/graphql/reference/gitlab_schema.json +++ b/doc/api/graphql/reference/gitlab_schema.json @@ -1404,6 +1404,16 @@ "defaultValue": null }, { + "name": "confidential", + "description": "Indicates if the epic is confidential. Will be ignored if `confidential_epics` feature flag is disabled", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { "name": "startDateFixed", "description": "The start date of the epic", "type": { @@ -5933,6 +5943,20 @@ "deprecationReason": null }, { + "name": "confidential", + "description": "Indicates if the epic is confidential", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "createdAt", "description": "Timestamp of the epic's creation", "args": [ @@ -27003,6 +27027,16 @@ "defaultValue": null }, { + "name": "confidential", + "description": "Indicates if the epic is confidential. Will be ignored if `confidential_epics` feature flag is disabled", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { "name": "startDateFixed", "description": "The start date of the epic", "type": { diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 43e8677f384..fe5925b95d9 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -335,6 +335,7 @@ Represents an epic. | --- | ---- | ---------- | | `author` | User! | Author of the epic | | `closedAt` | Time | Timestamp of the epic's closure | +| `confidential` | Boolean | Indicates if the epic is confidential | | `createdAt` | Time | Timestamp of the epic's creation | | `descendantCounts` | EpicDescendantCount | Number of open and closed descendant epics and issues | | `descendantWeightSum` | EpicDescendantWeights | Total weight of open and closed issues in the epic and its descendants | diff --git a/doc/user/incident_management/index.md b/doc/user/incident_management/index.md index 829fee47826..2b95128bffd 100644 --- a/doc/user/incident_management/index.md +++ b/doc/user/incident_management/index.md @@ -138,6 +138,4 @@ Incident Management features can be easily enabled & disabled via the Project se #### Auto-creation -GitLab Issues can automatically be created as a result of an Alert notification. An Issue created this way will contain error information to help you further debug the error. - -For [GitLab-managed alerting rules](../project/integrations/prometheus.md#setting-up-alerts-for-prometheus-metrics-ultimate), the issue will include an embedded chart for the query corresponding to the alert. The chart will show an hour of data surrounding the starting point of the incident, 30 minutes before and after. +You can automatically create GitLab issues from an Alert notification. Issues created this way contain error information to help you debug the error. Appropriately configured alerts include an [embedded chart](../project/integrations/prometheus.md#embedding-metrics-based-on-alerts-in-incident-issues) for the query corresponding to the alert. diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md index 273ab9095c0..4b07ecd2743 100644 --- a/doc/user/project/integrations/prometheus.md +++ b/doc/user/project/integrations/prometheus.md @@ -802,6 +802,22 @@ It is also possible to embed either the default dashboard metrics or individual ![Embedded Metrics in issue templates](img/embed_metrics_issue_template.png) +### Embedding metrics based on alerts in incident issues + +For [GitLab-managed alerting rules](#setting-up-alerts-for-prometheus-metrics-ultimate), the issue will include an embedded chart for the query corresponding to the alert. The chart displays an hour of data surrounding the starting point of the incident, 30 minutes before and after. + +For [manually configured Prometheus instances](#manual-configuration-of-prometheus), a chart corresponding to the query can be included if these requirements are met: + +- The alert corresponds to an environment managed through GitLab. +- The alert corresponds to a [range query](https://prometheus.io/docs/prometheus/latest/querying/api/#range-queries). +- The alert contains the required attributes listed in the chart below. + +| Attributes | Required | Description | +| ---------- | -------- | ----------- | +| `annotations/gitlab_environment_name` | Yes | Name of the GitLab-managed environment corresponding to the alert | +| One of `annotations/title`, `annotations/summary`, `labels/alertname` | Yes | Will be used as the chart title | +| `annotations/gitlab_y_label` | No | Will be used as the chart's y-axis label | + ### Embedding Cluster Health Charts **(ULTIMATE)** > [Introduced](<https://gitlab.com/gitlab-org/gitlab/issues/40997>) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9. diff --git a/doc/user/project/issues/img/issue_health_status_dropdown_v12_10.png b/doc/user/project/issues/img/issue_health_status_dropdown_v12_10.png Binary files differnew file mode 100644 index 00000000000..c0f0a0dfe16 --- /dev/null +++ b/doc/user/project/issues/img/issue_health_status_dropdown_v12_10.png diff --git a/doc/user/project/issues/index.md b/doc/user/project/issues/index.md index c020d6e5802..55e9967a370 100644 --- a/doc/user/project/issues/index.md +++ b/doc/user/project/issues/index.md @@ -177,7 +177,7 @@ that's progressing as planned or needs attention to keep on schedule: - **Needs attention** (amber) - **At risk** (red) -!["On track" health status on an issue](img/issue_health_status_v12_10.png) +!["On track" health status on an issue](img/issue_health_status_dropdown_v12_10.png) You can then see issue statuses on the [Epic tree](../../group/epics/index.md#issue-health-status-in-epic-tree-ultimate). diff --git a/lib/gitlab/alerting/alert.rb b/lib/gitlab/alerting/alert.rb index 531307b93d4..f6f52e392c6 100644 --- a/lib/gitlab/alerting/alert.rb +++ b/lib/gitlab/alerting/alert.rb @@ -69,6 +69,12 @@ module Gitlab end end + def y_label + strong_memoize(:y_label) do + parse_y_label_from_payload || title + end + end + def alert_markdown strong_memoize(:alert_markdown) do parse_alert_markdown_from_payload @@ -162,6 +168,10 @@ module Gitlab def parse_alert_markdown_from_payload payload&.dig('annotations', 'gitlab_incident_markdown') end + + def parse_y_label_from_payload + payload&.dig('annotations', 'gitlab_y_label') + end end end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 92df6cf3135..78d1ba110b9 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -3850,9 +3850,6 @@ msgstr "" msgid "Choose which shards you wish to synchronize to this secondary node" msgstr "" -msgid "Choose which status most accurately reflects the current state of this issue:" -msgstr "" - msgid "Choose your framework" msgstr "" @@ -16950,6 +16947,9 @@ msgstr "" msgid "Rename/Move" msgstr "" +msgid "Reopen" +msgstr "" + msgid "Reopen epic" msgstr "" @@ -17145,6 +17145,9 @@ msgstr "" msgid "Requirement" msgstr "" +msgid "Requirement title cannot have more than %{limit} characters." +msgstr "" + msgid "Requirements" msgstr "" @@ -18040,6 +18043,9 @@ msgstr "" msgid "Select groups to replicate" msgstr "" +msgid "Select health status" +msgstr "" + msgid "Select labels" msgstr "" @@ -18576,16 +18582,22 @@ msgstr "" msgid "Side-by-side" msgstr "" +msgid "Sidebar|Assign health status" +msgstr "" + msgid "Sidebar|Change weight" msgstr "" -msgid "Sidebar|None" +msgid "Sidebar|Health status" msgstr "" -msgid "Sidebar|Only numeral characters allowed" +msgid "Sidebar|No status" +msgstr "" + +msgid "Sidebar|None" msgstr "" -msgid "Sidebar|Status" +msgid "Sidebar|Only numeral characters allowed" msgstr "" msgid "Sidebar|Weight" @@ -18813,6 +18825,9 @@ msgstr "" msgid "Something went wrong while applying the suggestion. Please try again." msgstr "" +msgid "Something went wrong while archiving a requirement." +msgstr "" + msgid "Something went wrong while closing the %{issuable}. Please try again later" msgstr "" @@ -18885,6 +18900,9 @@ msgstr "" msgid "Something went wrong while performing the action." msgstr "" +msgid "Something went wrong while reopening a requirement." +msgstr "" + msgid "Something went wrong while reopening the %{issuable}. Please try again later" msgstr "" @@ -24957,9 +24975,6 @@ msgstr "" msgid "remove due date" msgstr "" -msgid "remove status" -msgstr "" - msgid "remove weight" msgstr "" diff --git a/spec/frontend/monitoring/components/charts/time_series_spec.js b/spec/frontend/monitoring/components/charts/time_series_spec.js index c9b670fd7a8..3aad4c87237 100644 --- a/spec/frontend/monitoring/components/charts/time_series_spec.js +++ b/spec/frontend/monitoring/components/charts/time_series_spec.js @@ -155,43 +155,56 @@ describe('Time series component', () => { describe('methods', () => { describe('formatTooltipText', () => { - let mockDate; - let mockCommitUrl; - let generateSeriesData; - - beforeEach(() => { - mockDate = deploymentData[0].created_at; - mockCommitUrl = deploymentData[0].commitUrl; - generateSeriesData = type => ({ - seriesData: [ - { - seriesName: timeSeriesChart.vm.chartData[0].name, - componentSubType: type, - value: [mockDate, 5.55555], - dataIndex: 0, - ...(type === 'scatter' && { name: 'deployments' }), - }, - ], - value: mockDate, - }); + const mockCommitUrl = deploymentData[0].commitUrl; + const mockDate = deploymentData[0].created_at; + const mockSha = 'f5bcd1d9'; + const mockLineSeriesData = () => ({ + seriesData: [ + { + seriesName: timeSeriesChart.vm.chartData[0].name, + componentSubType: 'line', + value: [mockDate, 5.55555], + dataIndex: 0, + }, + ], + value: mockDate, }); + const annotationsMetadata = { + tooltipData: { + sha: mockSha, + commitUrl: mockCommitUrl, + }, + }; + + const mockAnnotationsSeriesData = { + seriesData: [ + { + componentSubType: 'scatter', + seriesName: 'series01', + dataIndex: 0, + value: [mockDate, 5.55555], + type: 'scatter', + name: 'deployments', + }, + ], + value: mockDate, + }; + it('does not throw error if data point is outside the zoom range', () => { - const seriesDataWithoutValue = generateSeriesData('line'); - expect( - timeSeriesChart.vm.formatTooltipText({ - ...seriesDataWithoutValue, - seriesData: seriesDataWithoutValue.seriesData.map(data => ({ - ...data, - value: undefined, - })), - }), - ).toBeUndefined(); + const seriesDataWithoutValue = { + ...mockLineSeriesData(), + seriesData: mockLineSeriesData().seriesData.map(data => ({ + ...data, + value: undefined, + })), + }; + expect(timeSeriesChart.vm.formatTooltipText(seriesDataWithoutValue)).toBeUndefined(); }); describe('when series is of line type', () => { beforeEach(done => { - timeSeriesChart.vm.formatTooltipText(generateSeriesData('line')); + timeSeriesChart.vm.formatTooltipText(mockLineSeriesData()); timeSeriesChart.vm.$nextTick(done); }); @@ -223,7 +236,14 @@ describe('Time series component', () => { describe('when series is of scatter type, for deployments', () => { beforeEach(() => { - timeSeriesChart.vm.formatTooltipText(generateSeriesData('scatter')); + timeSeriesChart.vm.formatTooltipText({ + ...mockAnnotationsSeriesData, + seriesData: mockAnnotationsSeriesData.seriesData.map(data => ({ + ...data, + data: annotationsMetadata, + })), + }); + return timeSeriesChart.vm.$nextTick; }); it('set tooltip type to deployments', () => { @@ -242,6 +262,25 @@ describe('Time series component', () => { expect(timeSeriesChart.vm.tooltip.commitUrl).toBe(mockCommitUrl); }); }); + + describe('when series is of scatter type and deployments data is missing', () => { + beforeEach(() => { + timeSeriesChart.vm.formatTooltipText(mockAnnotationsSeriesData); + return timeSeriesChart.vm.$nextTick; + }); + + it('formats tooltip title', () => { + expect(timeSeriesChart.vm.tooltip.title).toBe('16 Jul 2019, 10:14AM'); + }); + + it('formats tooltip sha', () => { + expect(timeSeriesChart.vm.tooltip.sha).toBeUndefined(); + }); + + it('formats tooltip commit url', () => { + expect(timeSeriesChart.vm.tooltip.commitUrl).toBeUndefined(); + }); + }); }); describe('setSvg', () => { diff --git a/spec/lib/gitlab/alerting/alert_spec.rb b/spec/lib/gitlab/alerting/alert_spec.rb index aaded28954e..8b67cf949ce 100644 --- a/spec/lib/gitlab/alerting/alert_spec.rb +++ b/spec/lib/gitlab/alerting/alert_spec.rb @@ -192,6 +192,16 @@ describe Gitlab::Alerting::Alert do end end + describe '#y_label' do + subject { alert.y_label } + + it_behaves_like 'parse payload', 'annotations/gitlab_y_label' + + context 'when y_label is not included in the payload' do + it_behaves_like 'parse payload', 'annotations/title' + end + end + describe '#alert_markdown' do subject { alert.alert_markdown } diff --git a/spec/services/metrics/dashboard/custom_metric_embed_service_spec.rb b/spec/services/metrics/dashboard/custom_metric_embed_service_spec.rb index 2f03d18cd1f..1a9ddc87ab0 100644 --- a/spec/services/metrics/dashboard/custom_metric_embed_service_spec.rb +++ b/spec/services/metrics/dashboard/custom_metric_embed_service_spec.rb @@ -121,11 +121,18 @@ describe Metrics::Dashboard::CustomMetricEmbedService do it_behaves_like 'valid embedded dashboard service response' - it 'includes both metrics' do + it 'includes both metrics in a single panel' do result = service_call - included_queries = all_queries(result[:dashboard]) - expect(included_queries).to include('avg(metric_2)', 'avg(metric)') + panel_groups = result[:dashboard][:panel_groups] + panels = panel_groups[0][:panels] + metrics = panels[0][:metrics] + queries = metrics.map { |metric| metric[:query_range] } + + expect(panel_groups.length).to eq(1) + expect(panels.length).to eq(1) + expect(metrics.length).to eq(2) + expect(queries).to include('avg(metric_2)', 'avg(metric)') end end end @@ -136,16 +143,4 @@ describe Metrics::Dashboard::CustomMetricEmbedService do it_behaves_like 'misconfigured dashboard service response', :not_found end end - - private - - def all_queries(dashboard) - dashboard[:panel_groups].flat_map do |group| - group[:panels].flat_map do |panel| - panel[:metrics].map do |metric| - metric[:query_range] - end - end - end - end end |