diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-03 00:08:11 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-03 00:08:11 +0000 |
commit | bd8fb5668ae739a83d55ec5ca4a04344eef2167e (patch) | |
tree | baf085c6cd58b3b5e5a192d4d3db360d623bb056 | |
parent | 561e1b470f0a99fe6304c8f197348c47a637d594 (diff) | |
download | gitlab-ce-bd8fb5668ae739a83d55ec5ca4a04344eef2167e.tar.gz |
Add latest changes from gitlab-org/gitlab@master
22 files changed, 376 insertions, 257 deletions
diff --git a/app/serializers/diff_file_entity.rb b/app/serializers/diff_file_entity.rb index af7d1172f17..c3826692c52 100644 --- a/app/serializers/diff_file_entity.rb +++ b/app/serializers/diff_file_entity.rb @@ -53,7 +53,7 @@ class DiffFileEntity < DiffFileBaseEntity end # Used for inline diffs - expose :highlighted_diff_lines, using: DiffLineEntity, if: -> (diff_file, options) { inline_diff_view?(options) && diff_file.text? } do |diff_file| + expose :highlighted_diff_lines, using: DiffLineEntity, if: -> (diff_file, options) { inline_diff_view?(options, diff_file) && diff_file.text? } do |diff_file| diff_file.diff_lines_for_serializer end @@ -62,19 +62,19 @@ class DiffFileEntity < DiffFileBaseEntity end # Used for parallel diffs - expose :parallel_diff_lines, using: DiffLineParallelEntity, if: -> (diff_file, options) { parallel_diff_view?(options) && diff_file.text? } + expose :parallel_diff_lines, using: DiffLineParallelEntity, if: -> (diff_file, options) { parallel_diff_view?(options, diff_file) && diff_file.text? } private - def parallel_diff_view?(options) - return true unless Feature.enabled?(:single_mr_diff_view) + def parallel_diff_view?(options, diff_file) + return true unless Feature.enabled?(:single_mr_diff_view, diff_file.repository.project) # If we're not rendering inline, we must be rendering parallel - !inline_diff_view?(options) + !inline_diff_view?(options, diff_file) end - def inline_diff_view?(options) - return true unless Feature.enabled?(:single_mr_diff_view) + def inline_diff_view?(options, diff_file) + return true unless Feature.enabled?(:single_mr_diff_view, diff_file.repository.project) # If nothing is present, inline will be the default. options.fetch(:diff_view, :inline).to_sym == :inline diff --git a/changelogs/unreleased/sy-grafana-default-times.yml b/changelogs/unreleased/sy-grafana-default-times.yml new file mode 100644 index 00000000000..54b4f76c082 --- /dev/null +++ b/changelogs/unreleased/sy-grafana-default-times.yml @@ -0,0 +1,5 @@ +--- +title: Allow default time window on grafana embeds +merge_request: 21884 +author: +type: changed diff --git a/doc/api/members.md b/doc/api/members.md index 69c52a54a8d..e9131e2d4c3 100644 --- a/doc/api/members.md +++ b/doc/api/members.md @@ -17,6 +17,8 @@ The access levels are defined in the `Gitlab::Access` module. Currently, these l Gets a list of group or project members viewable by the authenticated user. Returns only direct members and not inherited members through ancestors groups. +This function takes pagination parameters `page` and `per_page` to restrict the list of users. + ```plaintext GET /groups/:id/members GET /projects/:id/members @@ -72,6 +74,8 @@ Gets a list of group or project members viewable by the authenticated user, incl When a user is a member of the project/group and of one or more ancestor groups the user is returned only once with the project `access_level` (if exists) or the `access_level` for the user in the first group which they belong to in the project groups ancestors chain. +This function takes pagination parameters `page` and `per_page` to restrict the list of users. + ```plaintext GET /groups/:id/members/all GET /projects/:id/members/all diff --git a/doc/development/import_export.md b/doc/development/import_export.md index 323ed48aaf9..252a57ce857 100644 --- a/doc/development/import_export.md +++ b/doc/development/import_export.md @@ -195,16 +195,17 @@ module Gitlab The [current version history](../user/project/settings/import_export.md) also displays the equivalent GitLab version and it is useful for knowing which versions won't be compatible between them. -| GitLab version | Import/Export version | -| ---------------- | --------------------- | -| 11.1 to current | 0.2.4 | -| 10.8 | 0.2.3 | -| 10.4 | 0.2.2 | -| ... | ... | -| 8.10.3 | 0.1.3 | -| 8.10.0 | 0.1.2 | -| 8.9.5 | 0.1.1 | -| 8.9.0 | 0.1.0 | +| Exporting GitLab version | Importing GitLab version | +| -------------------------- | -------------------------- | +| 11.7 to current | 11.7 to current | +| 11.1 to 11.6 | 11.1 to 11.6 | +| 10.8 to 11.0 | 10.8 to 11.0 | +| 10.4 to 10.7 | 10.4 to 10.7 | +| ... | ... | +| 8.10.3 to 8.11 | 8.10.3 to 8.11 | +| 8.10.0 to 8.10.2 | 8.10.0 to 8.10.2 | +| 8.9.5 to 8.9.11 | 8.9.5 to 8.9.11 | +| 8.9.0 to 8.9.4 | 8.9.0 to 8.9.4 | ### When to bump the version up @@ -223,28 +224,6 @@ Every time we bump the version, the integration specs will fail and can be fixed bundle exec rake gitlab:import_export:bump_version ``` -### Renaming columns or models - -This is a relatively common occurrence that will require a version bump. - -There is also the _RC problem_ - GitLab.com runs an RC, prior to any customers, -meaning that we want to bump the version up in the next version (or patch release). - -For example: - -1. Add rename to `RelationRenameService` in X.Y -1. Remove it from `RelationRenameService` in X.Y + 1 -1. Bump Import/Export version in X.Y + 1 - -```ruby -module Gitlab - module ImportExport - class RelationRenameService - RENAMES = { - 'pipelines' => 'ci_pipelines' # Added in 11.6, remove in 11.7 - }.freeze -``` - ## A quick dive into the code ### Import/Export configuration (`import_export.yml`) diff --git a/doc/development/what_requires_downtime.md b/doc/development/what_requires_downtime.md index a25d065f735..b7c667d034b 100644 --- a/doc/development/what_requires_downtime.md +++ b/doc/development/what_requires_downtime.md @@ -162,6 +162,9 @@ class CleanupUsersUpdatedAtRename < ActiveRecord::Migration[4.2] end ``` +NOTE: **Note:** If you're renaming a large table, please carefully consider the state when the first migration has run but the second cleanup migration hasn't been run yet. +With [Canary](https://about.gitlab.com/handbook/engineering/infrastructure/library/canary/) it is possible that the system runs in this state for a significant amount of time. + ## Changing Column Constraints Adding or removing a NOT NULL clause (or another constraint) can typically be diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md index bbe2f88795e..475eb4a55b9 100644 --- a/doc/user/project/integrations/prometheus.md +++ b/doc/user/project/integrations/prometheus.md @@ -769,7 +769,7 @@ Prerequisites for embedding from a Grafana instance: 1. In the upper-left corner of the page, select a specific value for each variable required for the queries in the chart. ![Select Query Variables](img/select_query_variables_v12_5.png) 1. In Grafana, click on a panel's title, then click **Share** to open the panel's sharing dialog to the **Link** tab. -1. If your Prometheus queries use Grafana's custom template variables, ensure that "Template variables" and "Current time range" options are toggled to **On**. Of Grafana global template variables, only `$__interval`, `$__from`, and `$__to` are currently supported. +1. If your Prometheus queries use Grafana's custom template variables, ensure that "Template variables" option is toggled to **On**. Of Grafana global template variables, only `$__interval`, `$__from`, and `$__to` are currently supported. Toggle **On** the "Current time range" option to specify the time range of the chart. Otherwise, the default range will be the last 8 hours. ![Grafana Sharing Dialog](img/grafana_sharing_dialog_v12_5.png) 1. Click **Copy** to copy the URL to the clipboard. 1. In GitLab, paste the URL into a Markdown field and save. The chart will take a few moments to render. diff --git a/doc/user/project/settings/import_export.md b/doc/user/project/settings/import_export.md index 1a4023b6ded..d32b4847230 100644 --- a/doc/user/project/settings/import_export.md +++ b/doc/user/project/settings/import_export.md @@ -42,22 +42,23 @@ Note the following: The following table lists updates to Import/Export: -| GitLab version | Import/Export schema version | -| ---------------- | --------------------- | -| 11.1 to current | 0.2.4 | -| 10.8 | 0.2.3 | -| 10.4 | 0.2.2 | -| 10.3 | 0.2.1 | -| 10.0 | 0.2.0 | -| 9.4.0 | 0.1.8 | -| 9.2.0 | 0.1.7 | -| 8.17.0 | 0.1.6 | -| 8.13.0 | 0.1.5 | -| 8.12.0 | 0.1.4 | -| 8.10.3 | 0.1.3 | -| 8.10.0 | 0.1.2 | -| 8.9.5 | 0.1.1 | -| 8.9.0 | 0.1.0 | +| Exporting GitLab version | Importing GitLab version | +| -------------------------- | -------------------------- | +| 11.7 to current | 11.7 to current | +| 11.1 to 11.6 | 11.1 to 11.6 | +| 10.8 to 11.0 | 10.8 to 11.0 | +| 10.4 to 10.7 | 10.4 to 10.7 | +| 10.3 | 10.3 | +| 10.0 to 10.2 | 10.0 to 10.2 | +| 9.4 to 9.6 | 9.4 to 9.6 | +| 9.2 to 9.3 | 9.2 to 9.3 | +| 8.17 to 9.1 | 8.17 to 9.1 | +| 8.13 to 8.16 | 8.13 to 8.16 | +| 8.12 | 8.12 | +| 8.10.3 to 8.11 | 8.10.3 to 8.11 | +| 8.10.0 to 8.10.2 | 8.10.0 to 8.10.2 | +| 8.9.5 to 8.9.11 | 8.9.5 to 8.9.11 | +| 8.9.0 to 8.9.4 | 8.9.0 to 8.9.4 | Projects can be exported and imported only between versions of GitLab with matching Import/Export versions. diff --git a/lib/banzai/filter/inline_grafana_metrics_filter.rb b/lib/banzai/filter/inline_grafana_metrics_filter.rb index 69ae747333f..60a16b164af 100644 --- a/lib/banzai/filter/inline_grafana_metrics_filter.rb +++ b/lib/banzai/filter/inline_grafana_metrics_filter.rb @@ -13,13 +13,16 @@ module Banzai super end + # @return [Hash<Symbol, String>] with keys :grafana_url, :start, and :end def embed_params(node) query_params = Gitlab::Metrics::Dashboard::Url.parse_query(node['href']) - return unless [:panelId, :from, :to].all? do |param| - query_params.include?(param) - end - { url: node['href'], start: query_params[:from], end: query_params[:to] } + return unless query_params.include?(:panelId) + + time_window = Grafana::TimeWindow.new(query_params[:from], query_params[:to]) + url = url_with_window(node['href'], query_params, time_window.in_milliseconds) + + { grafana_url: url }.merge(time_window.formatted) end # Selects any links with an href contains the configured @@ -44,18 +47,24 @@ module Banzai Gitlab::Routing.url_helpers.project_grafana_api_metrics_dashboard_url( project, embedded: true, - grafana_url: params[:url], - start: format_time(params[:start]), - end: format_time(params[:end]) + **params ) end - # Formats a timestamp from Grafana for compatibility with - # parsing in JS via `new Date(timestamp)` + # If the provided url is missing time window parameters, + # this inserts the default window into the url, allowing + # the embed service to correctly format prometheus + # queries during embed processing. # - # @param time [String] Represents miliseconds since epoch - def format_time(time) - Time.at(time.to_i / 1000).utc.strftime('%FT%TZ') + # @param url [String] + # @param query_params [Hash<Symbol, String>] + # @param time_window_params [Hash<Symbol, Integer>] + # @return [String] + def url_with_window(url, query_params, time_window_params) + uri = URI(url) + uri.query = time_window_params.merge(query_params).to_query + + uri.to_s end # Fetches a dashboard and caches the result for the diff --git a/lib/gitlab/import_export/project/tree_restorer.rb b/lib/gitlab/import_export/project/tree_restorer.rb index a5123f16dbc..904cb461ac3 100644 --- a/lib/gitlab/import_export/project/tree_restorer.rb +++ b/lib/gitlab/import_export/project/tree_restorer.rb @@ -21,8 +21,6 @@ module Gitlab @tree_hash = read_tree_hash @project_members = @tree_hash.delete('project_members') - RelationRenameService.rename(@tree_hash) - if relation_tree_restorer.restore import_failure_service.with_retry(action: 'set_latest_merge_request_diff_ids!') do @project.merge_requests.set_latest_merge_request_diff_ids! diff --git a/lib/gitlab/import_export/project/tree_saver.rb b/lib/gitlab/import_export/project/tree_saver.rb index 58f33a04851..32b3b518ece 100644 --- a/lib/gitlab/import_export/project/tree_saver.rb +++ b/lib/gitlab/import_export/project/tree_saver.rb @@ -35,8 +35,6 @@ module Gitlab end project_tree['project_members'] += group_members_array - - RelationRenameService.add_new_associations(project_tree) end def reader diff --git a/lib/gitlab/import_export/relation_rename_service.rb b/lib/gitlab/import_export/relation_rename_service.rb deleted file mode 100644 index 03aaa6aefc3..00000000000 --- a/lib/gitlab/import_export/relation_rename_service.rb +++ /dev/null @@ -1,48 +0,0 @@ -# frozen_string_literal: true - -# This class is intended to help with relation renames within Gitlab versions -# and allow compatibility between versions. -# If you have to change one relationship name that is imported/exported, -# you should add it to the RENAMES constant indicating the old name and the -# new one. -# The behavior of these renamed relationships should be transient and it should -# only last one release until you completely remove the renaming from the list. -# -# When importing, this class will check the hash and: -# - if only the old relationship name is found, it will rename it with the new one -# - if only the new relationship name is found, it will do nothing -# - if it finds both, it will use the new relationship data -# -# When exporting, this class will duplicate the keys in the resulting file. -# This way, if we open the file in an old version of the exporter it will work -# and also it will with the newer versions. -module Gitlab - module ImportExport - class RelationRenameService - RENAMES = { - 'pipelines' => 'ci_pipelines' # Added in 11.6, remove in 11.7 - }.freeze - - def self.rename(tree_hash) - return unless tree_hash&.present? - - RENAMES.each do |old_name, new_name| - old_entry = tree_hash.delete(old_name) - - next if tree_hash[new_name] - next unless old_entry - - tree_hash[new_name] = old_entry - end - end - - def self.add_new_associations(tree_hash) - RENAMES.each do |old_name, new_name| - next if tree_hash.key?(old_name) - - tree_hash[old_name] = tree_hash[new_name] - end - end - end - end -end diff --git a/lib/grafana/time_window.rb b/lib/grafana/time_window.rb new file mode 100644 index 00000000000..111e3ab7de2 --- /dev/null +++ b/lib/grafana/time_window.rb @@ -0,0 +1,130 @@ +# frozen_string_literal: true + +module Grafana + # Allows for easy formatting and manipulations of timestamps + # coming from a Grafana url + class TimeWindow + include ::Gitlab::Utils::StrongMemoize + + def initialize(from, to) + @from = from + @to = to + end + + def formatted + { + start: window[:from].formatted, + end: window[:to].formatted + } + end + + def in_milliseconds + window.transform_values(&:to_ms) + end + + private + + def window + strong_memoize(:window) do + specified_window + rescue Timestamp::Error + default_window + end + end + + def specified_window + RangeWithDefaults.new( + from: Timestamp.from_ms_since_epoch(@from), + to: Timestamp.from_ms_since_epoch(@to) + ).to_hash + end + + def default_window + RangeWithDefaults.new.to_hash + end + end + + # For incomplete time ranges, adds default parameters to + # achieve a complete range. If both full range is provided, + # range will be returned. + class RangeWithDefaults + DEFAULT_RANGE = 8.hours + + # @param from [Grafana::Timestamp, nil] Start of the expected range + # @param to [Grafana::Timestamp, nil] End of the expected range + def initialize(from: nil, to: nil) + @from = from + @to = to + + apply_defaults! + end + + def to_hash + { from: @from, to: @to }.compact + end + + private + + def apply_defaults! + @to ||= @from ? relative_end : Timestamp.new(Time.now) + @from ||= relative_start + end + + def relative_start + Timestamp.new(DEFAULT_RANGE.before(@to.time)) + end + + def relative_end + Timestamp.new(DEFAULT_RANGE.since(@from.time)) + end + end + + # Offers a consistent API for timestamps originating from + # Grafana or other sources, allowing for formatting of timestamps + # as consumed by Grafana-related utilities + class Timestamp + Error = Class.new(StandardError) + + attr_accessor :time + + # @param timestamp [Time] + def initialize(time) + @time = time + end + + # Formats a timestamp from Grafana for compatibility with + # parsing in JS via `new Date(timestamp)` + def formatted + time.utc.strftime('%FT%TZ') + end + + # Converts to milliseconds since epoch + def to_ms + time.to_i * 1000 + end + + class << self + # @param time [String] Representing milliseconds since epoch. + # This is what JS "decided" unix is. + def from_ms_since_epoch(time) + return if time.nil? + + raise Error.new('Expected milliseconds since epoch') unless ms_since_epoch?(time) + + new(cast_ms_to_time(time)) + end + + private + + def cast_ms_to_time(time) + Time.at(time.to_i / 1000.0) + end + + def ms_since_epoch?(time) + ms = time.to_i + + ms.to_s == time && ms.bit_length < 64 + end + end + end +end diff --git a/qa/qa/page/project/issue/show.rb b/qa/qa/page/project/issue/show.rb index a56083ea25c..8365ecb6348 100644 --- a/qa/qa/page/project/issue/show.rb +++ b/qa/qa/page/project/issue/show.rb @@ -127,7 +127,7 @@ module QA click_element(:edit_link_labels) labels.each do |label| - has_element?(:labels_block, text: label) + has_element?(:labels_block, text: label, wait: 0) end refresh diff --git a/scripts/trigger-build b/scripts/trigger-build index c14a3633075..6359446ecd1 100755 --- a/scripts/trigger-build +++ b/scripts/trigger-build @@ -16,6 +16,14 @@ module Trigger %w[gitlab gitlab-ee].include?(ENV['CI_PROJECT_NAME']) end + def self.non_empty_variable_value(variable) + variable_value = ENV[variable] + + return if variable_value.nil? || variable_value.empty? + + variable_value + end + class Base def invoke!(post_comment: false, downstream_job_name: nil) pipeline_variables = variables @@ -84,14 +92,15 @@ module Trigger end def base_variables - # Use CI_MERGE_REQUEST_SOURCE_BRANCH_SHA for omnibus checkouts due to pipeline for merged results + # Use CI_MERGE_REQUEST_SOURCE_BRANCH_SHA for omnibus checkouts due to pipeline for merged results, + # and fallback to CI_COMMIT_SHA for the `detached` pipelines. { 'GITLAB_REF_SLUG' => ENV['CI_COMMIT_TAG'] ? ENV['CI_COMMIT_REF_NAME'] : ENV['CI_COMMIT_REF_SLUG'], 'TRIGGERED_USER' => ENV['TRIGGERED_USER'] || ENV['GITLAB_USER_NAME'], 'TRIGGER_SOURCE' => ENV['CI_JOB_URL'], 'TOP_UPSTREAM_SOURCE_PROJECT' => ENV['CI_PROJECT_PATH'], 'TOP_UPSTREAM_SOURCE_JOB' => ENV['CI_JOB_URL'], - 'TOP_UPSTREAM_SOURCE_SHA' => ENV['CI_MERGE_REQUEST_SOURCE_BRANCH_SHA'], + 'TOP_UPSTREAM_SOURCE_SHA' => Trigger.non_empty_variable_value('CI_MERGE_REQUEST_SOURCE_BRANCH_SHA') || ENV['CI_COMMIT_SHA'], 'TOP_UPSTREAM_SOURCE_REF' => ENV['CI_COMMIT_REF_NAME'], 'TOP_UPSTREAM_MERGE_REQUEST_PROJECT_ID' => ENV['CI_MERGE_REQUEST_PROJECT_ID'], 'TOP_UPSTREAM_MERGE_REQUEST_IID' => ENV['CI_MERGE_REQUEST_IID'] @@ -127,8 +136,9 @@ module Trigger def extra_variables # Use CI_MERGE_REQUEST_SOURCE_BRANCH_SHA for omnibus checkouts due to pipeline for merged results + # and fallback to CI_COMMIT_SHA for the `detached` pipelines. { - 'GITLAB_VERSION' => ENV['CI_MERGE_REQUEST_SOURCE_BRANCH_SHA'], + 'GITLAB_VERSION' => Trigger.non_empty_variable_value('CI_MERGE_REQUEST_SOURCE_BRANCH_SHA') || ENV['CI_COMMIT_SHA'], 'ALTERNATIVE_SOURCES' => 'true', 'ee' => Trigger.ee? ? 'true' : 'false', 'QA_BRANCH' => ENV['QA_BRANCH'] || 'master' @@ -194,7 +204,7 @@ module Trigger Gitlab.create_commit_comment( ENV['CI_PROJECT_PATH'], - ENV['CI_MERGE_REQUEST_SOURCE_BRANCH_SHA'], + Trigger.non_empty_variable_value('CI_MERGE_REQUEST_SOURCE_BRANCH_SHA') || ENV['CI_COMMIT_SHA'], "The [`#{ENV['CI_JOB_NAME']}`](#{ENV['CI_JOB_URL']}) job from pipeline #{ENV['CI_PIPELINE_URL']} triggered #{downstream_pipeline.web_url} downstream.") rescue Gitlab::Error::Error => error diff --git a/spec/features/merge_request/maintainer_edits_fork_spec.rb b/spec/features/merge_request/maintainer_edits_fork_spec.rb index 17ff494a6fa..f1ee6aaa897 100644 --- a/spec/features/merge_request/maintainer_edits_fork_spec.rb +++ b/spec/features/merge_request/maintainer_edits_fork_spec.rb @@ -20,7 +20,7 @@ describe 'a maintainer edits files on a source-branch of an MR from a fork', :js end before do - stub_feature_flags(web_ide_default: false, single_mr_diff_view: false, code_navigation: false) + stub_feature_flags(web_ide_default: false, single_mr_diff_view: { enabled: false, thing: target_project }, code_navigation: false) target_project.add_maintainer(user) sign_in(user) diff --git a/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb b/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb index 92d90926c0a..8633d67f875 100644 --- a/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb +++ b/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb @@ -10,7 +10,7 @@ describe 'Batch diffs', :js do let(:merge_request) { create(:merge_request, source_project: project, source_branch: 'master', target_branch: 'empty-branch') } before do - stub_feature_flags(single_mr_diff_view: true) + stub_feature_flags(single_mr_diff_view: { enabled: true, thing: project }) stub_feature_flags(diffs_batch_load: true) sign_in(project.owner) diff --git a/spec/fixtures/lib/gitlab/import_export/complex/project.json b/spec/fixtures/lib/gitlab/import_export/complex/project.json index 4d6211a1251..fae02540868 100644 --- a/spec/fixtures/lib/gitlab/import_export/complex/project.json +++ b/spec/fixtures/lib/gitlab/import_export/complex/project.json @@ -6318,7 +6318,7 @@ ] } ], - "pipelines": [ + "ci_pipelines": [ { "id": 36, "project_id": 5, diff --git a/spec/lib/banzai/filter/inline_grafana_metrics_filter_spec.rb b/spec/lib/banzai/filter/inline_grafana_metrics_filter_spec.rb index 9ac06a90efd..2092b9e9db8 100644 --- a/spec/lib/banzai/filter/inline_grafana_metrics_filter_spec.rb +++ b/spec/lib/banzai/filter/inline_grafana_metrics_filter_spec.rb @@ -10,18 +10,20 @@ describe Banzai::Filter::InlineGrafanaMetricsFilter do let(:input) { %(<a href="#{trigger_url}">example</a>) } let(:doc) { filter(input) } + let(:embed_url) { doc.at_css('.js-render-metrics')['data-dashboard-url'] } + let(:dashboard_path) do '/d/XDaNK6amz/gitlab-omnibus-redis' \ - '?from=1570397739557&to=1570484139557' \ - '&var-instance=All&panelId=14' + '?from=1570397739557&panelId=14' \ + '&to=1570484139557&var-instance=All' end let(:trigger_url) { grafana_integration.grafana_url + dashboard_path } let(:dashboard_url) do urls.project_grafana_api_metrics_dashboard_url( project, - embedded: true, grafana_url: trigger_url, + embedded: true, start: "2019-10-06T21:35:39Z", end: "2019-10-07T21:35:39Z" ) @@ -29,6 +31,10 @@ describe Banzai::Filter::InlineGrafanaMetricsFilter do it_behaves_like 'a metrics embed filter' + around do |example| + Timecop.freeze(Time.utc(2019, 3, 17, 13, 10)) { example.run } + end + context 'when grafana is not configured' do before do allow(project).to receive(:grafana_integration).and_return(nil) @@ -39,7 +45,7 @@ describe Banzai::Filter::InlineGrafanaMetricsFilter do end end - context 'when parameters are missing' do + context 'when "panelId" parameter is missing' do let(:dashboard_path) { '/d/XDaNK6amz/gitlab-omnibus-redis' } it 'leaves the markdown unchanged' do @@ -47,6 +53,39 @@ describe Banzai::Filter::InlineGrafanaMetricsFilter do end end + context 'when time window parameters are missing' do + let(:dashboard_path) { '/d/XDaNK6amz/gitlab-omnibus-redis?panelId=16' } + + it 'sets the window to the last 8 hrs' do + expect(embed_url).to include( + 'from%3D1552799400000', 'to%3D1552828200000', + 'start=2019-03-17T05%3A10%3A00Z', 'end=2019-03-17T13%3A10%3A00Z' + ) + end + end + + context 'when "to" parameter is missing' do + let(:dashboard_path) { '/d/XDaNK6amz/gitlab-omnibus-redis?panelId=16&from=1570397739557' } + + it 'sets "to" to 8 hrs after "from"' do + expect(embed_url).to include( + 'from%3D1570397739557', 'to%3D1570426539000', + 'start=2019-10-06T21%3A35%3A39Z', 'end=2019-10-07T05%3A35%3A39Z' + ) + end + end + + context 'when "from" parameter is missing' do + let(:dashboard_path) { '/d/XDaNK6amz/gitlab-omnibus-redis?panelId=16&to=1570484139557' } + + it 'sets "from" to 8 hrs before "to"' do + expect(embed_url).to include( + 'from%3D1570455339000', 'to%3D1570484139557', + 'start=2019-10-07T13%3A35%3A39Z', 'end=2019-10-07T21%3A35%3A39Z' + ) + end + end + private # Nokogiri escapes the URLs, but we don't care about that diff --git a/spec/lib/gitlab/import_export/import_test_coverage_spec.rb b/spec/lib/gitlab/import_export/import_test_coverage_spec.rb index 97d5ce07d47..335b0031147 100644 --- a/spec/lib/gitlab/import_export/import_test_coverage_spec.rb +++ b/spec/lib/gitlab/import_export/import_test_coverage_spec.rb @@ -89,8 +89,6 @@ describe 'Test coverage of the Project Import' do def relations_from_json(json_file) json = ActiveSupport::JSON.decode(IO.read(json_file)) - Gitlab::ImportExport::RelationRenameService.rename(json) - [].tap {|res| gather_relations({ project: json }, res, [])} .map {|relation_names| relation_names.join('.')} end diff --git a/spec/lib/gitlab/import_export/relation_rename_service_spec.rb b/spec/lib/gitlab/import_export/relation_rename_service_spec.rb deleted file mode 100644 index 2e251154e9f..00000000000 --- a/spec/lib/gitlab/import_export/relation_rename_service_spec.rb +++ /dev/null @@ -1,122 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe Gitlab::ImportExport::RelationRenameService do - include ImportExport::CommonUtil - - let(:renames) do - { - 'example_relation1' => 'new_example_relation1', - 'example_relation2' => 'new_example_relation2' - } - end - - let(:user) { create(:admin) } - let(:group) { create(:group, :nested) } - let!(:project) { create(:project, :builds_disabled, :issues_disabled, group: group, name: 'project', path: 'project') } - let(:shared) { project.import_export_shared } - - before do - stub_const("#{described_class}::RENAMES", renames) - end - - context 'when importing' do - let(:project_tree_restorer) { Gitlab::ImportExport::Project::TreeRestorer.new(user: user, shared: shared, project: project) } - let(:file_content) { IO.read(File.join(shared.export_path, 'project.json')) } - let(:json_file) { ActiveSupport::JSON.decode(file_content) } - - before do - setup_import_export_config('complex') - - allow(ActiveSupport::JSON).to receive(:decode).and_call_original - allow(ActiveSupport::JSON).to receive(:decode).with(file_content).and_return(json_file) - end - - context 'when the file has only old relationship names' do - # Configuring the json as an old version exported file, with only - # the previous association with the old name - before do - renames.each do |old_name, _| - json_file[old_name.to_s] = [] - end - end - - it 'renames old relationships to the new name' do - expect(json_file.keys).to include(*renames.keys) - - project_tree_restorer.restore - - expect(json_file.keys).to include(*renames.values) - expect(json_file.keys).not_to include(*renames.keys) - end - end - - context 'when the file has both the old and new relationships' do - # Configuring the json as the new version exported file, with both - # the old association name and the new one - before do - renames.each do |old_name, new_name| - json_file[old_name.to_s] = [1] - json_file[new_name.to_s] = [2] - end - end - - it 'uses the new relationships and removes the old ones from the hash' do - expect(json_file.keys).to include(*renames.keys) - - project_tree_restorer.restore - - expect(json_file.keys).to include(*renames.values) - expect(json_file.values_at(*renames.values).flatten.uniq.first).to eq 2 - expect(json_file.keys).not_to include(*renames.keys) - end - end - - context 'when the file has only new relationship names' do - # Configuring the json as the future version exported file, with only - # the new association name - before do - renames.each do |_, new_name| - json_file[new_name.to_s] = [] - end - end - - it 'uses the new relationships' do - expect(json_file.keys).not_to include(*renames.keys) - - project_tree_restorer.restore - - expect(json_file.keys).to include(*renames.values) - end - end - end - - context 'when exporting' do - let(:export_content_path) { project_tree_saver.full_path } - let(:export_content_hash) { ActiveSupport::JSON.decode(File.read(export_content_path)) } - let(:injected_hash) { renames.values.product([{}]).to_h } - let(:relation_tree_saver) { Gitlab::ImportExport::RelationTreeSaver.new } - - let(:project_tree_saver) do - Gitlab::ImportExport::Project::TreeSaver.new( - project: project, current_user: user, shared: shared) - end - - before do - allow(project_tree_saver).to receive(:tree_saver).and_return(relation_tree_saver) - end - - it 'adds old relationships to the exported file' do - # we inject relations with new names that should be rewritten - expect(relation_tree_saver).to receive(:serialize).and_wrap_original do |method, *args| - method.call(*args).merge(injected_hash) - end - - expect(project_tree_saver.save).to eq(true) - - expect(export_content_hash.keys).to include(*renames.keys) - expect(export_content_hash.keys).to include(*renames.values) - end - end -end diff --git a/spec/lib/grafana/time_window_spec.rb b/spec/lib/grafana/time_window_spec.rb new file mode 100644 index 00000000000..e70861658ca --- /dev/null +++ b/spec/lib/grafana/time_window_spec.rb @@ -0,0 +1,115 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Grafana::TimeWindow do + let(:from) { '1552799400000' } + let(:to) { '1552828200000' } + + around do |example| + Timecop.freeze(Time.utc(2019, 3, 17, 13, 10)) { example.run } + end + + describe '#formatted' do + subject { described_class.new(from, to).formatted } + + it { is_expected.to eq(start: "2019-03-17T05:10:00Z", end: "2019-03-17T13:10:00Z") } + end + + describe '#in_milliseconds' do + subject { described_class.new(from, to).in_milliseconds } + + it { is_expected.to eq(from: 1552799400000, to: 1552828200000) } + + context 'when non-unix parameters are provided' do + let(:to) { Time.now.to_s } + + let(:default_from) { 8.hours.ago.to_i * 1000 } + let(:default_to) { Time.now.to_i * 1000 } + + it { is_expected.to eq(from: default_from, to: default_to) } + end + end +end + +describe Grafana::RangeWithDefaults do + let(:from) { Grafana::Timestamp.from_ms_since_epoch('1552799400000') } + let(:to) { Grafana::Timestamp.from_ms_since_epoch('1552828200000') } + + around do |example| + Timecop.freeze(Time.utc(2019, 3, 17, 13, 10)) { example.run } + end + + describe '#to_hash' do + subject { described_class.new(from: from, to: to).to_hash } + + it { is_expected.to eq(from: from, to: to) } + + context 'when only "to" is provided' do + let(:from) { nil } + + it 'has the expected properties' do + expect(subject[:to]).to eq(to) + expect(subject[:from].time).to eq(to.time - 8.hours) + end + end + + context 'when only "from" is provided' do + let(:to) { nil } + + it 'has the expected properties' do + expect(subject[:to].time).to eq(from.time + 8.hours) + expect(subject[:from]).to eq(from) + end + end + + context 'when no parameters are provided' do + let(:to) { nil } + let(:from) { nil } + + let(:default_from) { 8.hours.ago } + let(:default_to) { Time.now } + + it 'has the expected properties' do + expect(subject[:to].time).to eq(default_to) + expect(subject[:from].time).to eq(default_from) + end + end + end +end + +describe Grafana::Timestamp do + let(:timestamp) { Time.at(1552799400) } + + around do |example| + Timecop.freeze(Time.utc(2019, 3, 17, 13, 10)) { example.run } + end + + describe '#formatted' do + subject { described_class.new(timestamp).formatted } + + it { is_expected.to eq "2019-03-17T05:10:00Z" } + end + + describe '#to_ms' do + subject { described_class.new(timestamp).to_ms } + + it { is_expected.to eq 1552799400000 } + end + + describe '.from_ms_since_epoch' do + let(:timestamp) { '1552799400000' } + + subject { described_class.from_ms_since_epoch(timestamp) } + + it { is_expected.to be_a described_class } + + context 'when the input is not a unix-ish timestamp' do + let(:timestamp) { Time.now.to_s } + + it 'raises an error' do + expect { subject }.to raise_error(Grafana::Timestamp::Error) + end + end + end +end diff --git a/spec/support/shared_examples/serializers/diff_file_entity_shared_examples.rb b/spec/support/shared_examples/serializers/diff_file_entity_shared_examples.rb index db5c4b45b70..b6c4841dbd4 100644 --- a/spec/support/shared_examples/serializers/diff_file_entity_shared_examples.rb +++ b/spec/support/shared_examples/serializers/diff_file_entity_shared_examples.rb @@ -60,7 +60,7 @@ RSpec.shared_examples 'diff file entity' do context 'when the `single_mr_diff_view` feature is disabled' do before do - stub_feature_flags(single_mr_diff_view: false) + stub_feature_flags(single_mr_diff_view: { enabled: false, thing: project }) end it 'contains both kinds of diffs' do |