diff --git a/Gemfile b/Gemfile index eab05b33972..0daa5b77e2f 100644 --- a/Gemfile +++ b/Gemfile @@ -347,7 +347,7 @@ gem 'warning', '~> 1.3.0' group :development do gem 'lefthook', '~> 1.0.0', require: false gem 'rubocop' - gem 'solargraph', '~> 0.44.3', require: false + gem 'solargraph', '~> 0.45.0', require: false gem 'letter_opener_web', '~> 2.0.0' diff --git a/Gemfile.lock b/Gemfile.lock index ddba30d2574..014a863e77d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -310,7 +310,7 @@ GEM devise (~> 4.0) railties (< 7.1) rotp (~> 6.0) - diff-lcs (1.4.4) + diff-lcs (1.5.0) diff_match_patch (0.1.0) diffy (3.3.0) discordrb-webhooks (3.4.2) @@ -744,7 +744,7 @@ GEM grpc (~> 1.0) knapsack (1.21.1) rake - kramdown (2.3.1) + kramdown (2.3.2) rexml kramdown-parser-gfm (1.1.0) kramdown (~> 2.0) @@ -838,7 +838,7 @@ GEM netrc (0.11.0) nio4r (2.5.8) no_proxy_fix (0.1.2) - nokogiri (1.13.6) + nokogiri (1.13.7) mini_portile2 (~> 2.8.0) racc (~> 1.4) notiffany (0.1.3) @@ -1172,7 +1172,7 @@ GEM rubocop-ast (>= 0.6.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 2.0) - rubocop-ast (1.18.0) + rubocop-ast (1.19.1) parser (>= 3.1.1.0) rubocop-gitlab-security (0.1.1) rubocop (>= 0.51) @@ -1281,7 +1281,7 @@ GEM slack-messenger (2.3.4) snowplow-tracker (0.6.1) contracts (~> 0.7, <= 0.11) - solargraph (0.44.3) + solargraph (0.45.0) backport (~> 1.2) benchmark bundler (>= 1.17.2) @@ -1730,7 +1730,7 @@ DEPENDENCIES simplecov-lcov (~> 0.8.0) slack-messenger (~> 2.3.4) snowplow-tracker (~> 0.6.1) - solargraph (~> 0.44.3) + solargraph (~> 0.45.0) spamcheck (~> 0.1.0) spring (~> 2.1.0) spring-commands-rspec (~> 1.0.4) diff --git a/app/assets/javascripts/boards/components/board_card_inner.vue b/app/assets/javascripts/boards/components/board_card_inner.vue index a632f5ae0ed..45b53b13a7f 100644 --- a/app/assets/javascripts/boards/components/board_card_inner.vue +++ b/app/assets/javascripts/boards/components/board_card_inner.vue @@ -367,6 +367,7 @@ export default { :img-alt="avatarUrlTitle(assignee)" :img-src="avatarUrl(assignee)" :img-size="24" + img-css-classes="avatar gl-mr-0!" class="js-no-trigger" tooltip-placement="bottom" > diff --git a/app/assets/javascripts/editor/extensions/source_editor_markdown_livepreview_ext.js b/app/assets/javascripts/editor/extensions/source_editor_markdown_livepreview_ext.js index e4ad0bf8e76..bc3cb163c39 100644 --- a/app/assets/javascripts/editor/extensions/source_editor_markdown_livepreview_ext.js +++ b/app/assets/javascripts/editor/extensions/source_editor_markdown_livepreview_ext.js @@ -1,3 +1,4 @@ +import { KeyMod, KeyCode } from 'monaco-editor'; import { debounce } from 'lodash'; import { BLOB_PREVIEW_ERROR } from '~/blob_edit/constants'; import createFlash from '~/flash'; @@ -158,8 +159,8 @@ export class EditorMarkdownPreviewExtension { if (instance.getAction(EXTENSION_MARKDOWN_PREVIEW_ACTION_ID)) return; const actionBasis = { keybindings: [ - // eslint-disable-next-line no-bitwise,no-undef - monaco.KeyMod.chord(monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.KEY_P), + // eslint-disable-next-line no-bitwise + KeyMod.chord(KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_P), ], contextMenuGroupId: 'navigation', contextMenuOrder: 1.5, diff --git a/app/assets/javascripts/linked_resources/index.js b/app/assets/javascripts/linked_resources/index.js index 802364acff9..6d799d30b4b 100644 --- a/app/assets/javascripts/linked_resources/index.js +++ b/app/assets/javascripts/linked_resources/index.js @@ -27,8 +27,8 @@ export default function initLinkedResources() { render: (createElement) => createElement('resource-links-block', { props: { - issuableId, helpPath, + issuableId: parseInt(issuableId, 10), canAddResourceLinks: parseBoolean(canAddResourceLinks), }, }), diff --git a/app/assets/javascripts/test_utils/index.js b/app/assets/javascripts/test_utils/index.js index 2727485fb95..369cf9714e8 100644 --- a/app/assets/javascripts/test_utils/index.js +++ b/app/assets/javascripts/test_utils/index.js @@ -1,8 +1,10 @@ +import { editor } from 'monaco-editor'; import { Sortable } from 'sortablejs'; import simulateDrag from './simulate_drag'; import simulateInput from './simulate_input'; // Export to global space for rspec to use +window.localMonaco = editor; window.simulateDrag = simulateDrag; window.simulateInput = simulateInput; window.Sortable = Sortable; diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/README.md b/app/assets/javascripts/vue_merge_request_widget/components/extensions/README.md new file mode 100644 index 00000000000..e5bb4e1af4c --- /dev/null +++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/README.md @@ -0,0 +1,64 @@ +### Widget Extensions + +#### Telemetry + +Telemetry is enabled by default in all widget extensions. + +However, telemetry events are not reported until they have been marked as a "known event" with a Metric Dictionary. + +If telemetry metrics are desired when adding a widget extension, it is important to also create known events. + +The following steps are needed to generate these known events for a single widget: + +1. Widgets should be named `Widget${CamelName}`. + - For example: a widget for "Test Reports" should be `WidgetTestReports` +1. "Compute" the widget name slug by converting the `${CamelName}` to lower-, snake-case. + - The above example would be `test_reports` +1. Add the new widget name slug to `lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb` in the `WIDGETS` list. +1. Ensure the GDK is running (`gdk start`) +1. Generate known events on the command line with the following command. Replace `test_reports` with your appropriate name slug. + ``` + bundle exec rails generate gitlab:usage_metric_definition \ + counts.code_review.i_merge_request_widget_test_reports_count_view \ + counts.code_review.i_merge_request_widget_test_reports_count_full_report_clicked \ + counts.code_review.i_merge_request_widget_test_reports_count_expand \ + counts.code_review.i_merge_request_widget_test_reports_count_expand_success \ + counts.code_review.i_merge_request_widget_test_reports_count_expand_warning \ + counts.code_review.i_merge_request_widget_test_reports_count_expand_failed \ + --dir=all + ``` +1. Modify each newly generated file so that they match the existing files for MR Widget Extension telemetry. + - You can find existing examples by doing a glob search like so: `metrics/**/*_i_code_review_merge_request_widget_*` + - Roughly-speaking, each file should have these values: + 1. `description` = A plain English description of this value. Please see existing widget extension telemetry files for examples. + 1. `product_section` = `dev` + 1. `product_stage` = `create` + 1. `product_group` = `code_review` + 1. `product_category` = `code_review` + 1. `introduced_by_url` = `'[your MR]'` + 1. `options.events` = (the event in the command from above that generated this file, like `i_code_review_merge_request_widget_test_reports_count_view`) + - This is how the telemetry events are linked to "metrics" so this is probably one of the more important values + 1. `data_source` = `redis` + 1. `data_category` = `optional` +1. Repeat steps 5 and 6 for the HLL metrics. Replace `test_reports` with your appropriate name slug. + ``` + bundle exec rails generate gitlab:usage_metric_definition:redis_hll code_review \ + i_code_review_merge_request_widget_test_reports_view \ + i_code_review_merge_request_widget_test_reports_full_report_clicked \ + i_code_review_merge_request_widget_test_reports_expand \ + i_code_review_merge_request_widget_test_reports_expand_success \ + i_code_review_merge_request_widget_test_reports_expand_warning \ + i_code_review_merge_request_widget_test_reports_expand_failed \ + --class_name=RedisHLLMetric + ``` + - In step 6 for HLL, change the `data_source` to `redis_hll`. +1. Add each of the HLL metrics to `lib/gitlab/usage_data_counters/known_events/code_review_events.yml` + 1. `name` = [the event] + 1. `redis_slot` = `code_review` + 1. `category` = `code_review` + 1. `aggregation` = `weekly` +1. Add each event to the appropriate aggregates in `config/metrics/aggregates/code_review.yml` + +##### New Events + +If you are adding a new event to our known events, it will need to be included in `lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb`. Update the list of `KNOWN_EVENTS` with the new event(s). diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss index 41265de0ca0..00ae509ad15 100644 --- a/app/assets/stylesheets/framework/files.scss +++ b/app/assets/stylesheets/framework/files.scss @@ -576,10 +576,10 @@ span.idiff { } } -// *:nth-of-type(1n+5) - makes sure we do not render elements 5+ right away when +// *:nth-of-type(1n+30) - makes sure we do not render elements 30+ right away when // viewing a file. Even though the HTML is injected in the DOM, as long as we do // not render those elements, the browser doesn't need to spend resources // calculating and repainting what's hidden. -.file-holder [data-loading] .file-content *:nth-of-type(1n+5) { +.file-holder [data-loading] .file-content *:nth-of-type(1n+30) { @include gl-display-none; } diff --git a/app/controllers/profiles/personal_access_tokens_controller.rb b/app/controllers/profiles/personal_access_tokens_controller.rb index a8d8e1e38a3..07d786ab060 100644 --- a/app/controllers/profiles/personal_access_tokens_controller.rb +++ b/app/controllers/profiles/personal_access_tokens_controller.rb @@ -58,7 +58,7 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController end def active_personal_access_tokens - tokens = finder(state: 'active', sort: 'expires_at_asc').execute + tokens = finder(state: 'active', sort: 'expires_at_asc_id_desc').execute if Feature.enabled?('access_token_pagination') tokens = tokens.page(page) diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 0c1cc6eb1b0..3a8e68c58a6 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -102,6 +102,7 @@ module Ci has_one :chat_data, class_name: 'Ci::PipelineChatData' has_many :triggered_pipelines, through: :sourced_pipelines, source: :pipeline + # Only includes direct and not nested children has_many :child_pipelines, -> { merge(Ci::Sources::Pipeline.same_project) }, through: :sourced_pipelines, source: :pipeline has_one :triggered_by_pipeline, through: :source_pipeline, source: :source_pipeline has_one :parent_pipeline, -> { merge(Ci::Sources::Pipeline.same_project) }, through: :source_pipeline, source: :source_pipeline @@ -592,26 +593,20 @@ module Ci canceled? && auto_canceled_by_id? end - def cancel_running(retries: 1) - preloaded_relations = [:project, :pipeline, :deployment, :taggings] + # Cancel a pipelines cancelable jobs and optionally it's child pipelines cancelable jobs + # retries - # of times to retry if errors + # cascade_to_children - if true cancels all related child pipelines for parent child pipelines + # auto_canceled_by_pipeline_id - store the pipeline_id of the pipeline that triggered cancellation + # execute_async - if true cancel the children asyncronously + def cancel_running(retries: 1, cascade_to_children: true, auto_canceled_by_pipeline_id: nil, execute_async: true) + update(auto_canceled_by_id: auto_canceled_by_pipeline_id) if auto_canceled_by_pipeline_id - retry_lock(cancelable_statuses, retries, name: 'ci_pipeline_cancel_running') do |cancelables| - cancelables.find_in_batches do |batch| - Preloaders::CommitStatusPreloader.new(batch).execute(preloaded_relations) + cancel_jobs(cancelable_statuses, retries: retries, auto_canceled_by_pipeline_id: auto_canceled_by_pipeline_id) - batch.each do |job| - yield(job) if block_given? - job.cancel - end - end - end - end - - def auto_cancel_running(pipeline, retries: 1) - update(auto_canceled_by: pipeline) - - cancel_running(retries: retries) do |job| - job.auto_canceled_by = pipeline + if cascade_to_children && project.cascade_cancel_pipelines_enabled? + # cancel any bridges that could spin up new child pipelines + cancel_jobs(bridges_in_self_and_descendants.cancelable, retries: retries, auto_canceled_by_pipeline_id: auto_canceled_by_pipeline_id) + cancel_children(auto_canceled_by_pipeline_id: auto_canceled_by_pipeline_id, execute_async: execute_async) end end @@ -953,6 +948,10 @@ module Ci Ci::Build.latest.where(pipeline: self_and_descendants) end + def bridges_in_self_and_descendants + Ci::Bridge.latest.where(pipeline: self_and_descendants) + end + def environments_in_self_and_descendants(deployment_status: nil) # We limit to 100 unique environments for application safety. # See: https://gitlab.com/gitlab-org/gitlab/-/issues/340781#note_699114700 @@ -986,6 +985,11 @@ module Ci object_hierarchy(project_condition: :same).base_and_descendants end + # With only parent-child pipelines + def all_child_pipelines + object_hierarchy(project_condition: :same).descendants + end + def self_and_descendants_complete? self_and_descendants.all?(&:complete?) end @@ -1323,6 +1327,42 @@ module Ci private + def cancel_jobs(jobs, retries: 1, auto_canceled_by_pipeline_id: nil) + retry_lock(jobs, retries, name: 'ci_pipeline_cancel_running') do |statuses| + preloaded_relations = [:project, :pipeline, :deployment, :taggings] + + statuses.find_in_batches do |status_batch| + relation = CommitStatus.where(id: status_batch) + Preloaders::CommitStatusPreloader.new(relation).execute(preloaded_relations) + + relation.each do |job| + job.auto_canceled_by_id = auto_canceled_by_pipeline_id if auto_canceled_by_pipeline_id + job.cancel + end + end + end + end + + # For parent child-pipelines only (not multi-project) + def cancel_children(auto_canceled_by_pipeline_id: nil, execute_async: true) + all_child_pipelines.each do |child_pipeline| + if execute_async + ::Ci::CancelPipelineWorker.perform_async( + child_pipeline.id, + auto_canceled_by_pipeline_id + ) + else + child_pipeline.cancel_running( + # cascade_to_children is false because we iterate through children + # we also cancel bridges prior to prevent more children + cascade_to_children: false, + execute_async: execute_async, + auto_canceled_by_pipeline_id: auto_canceled_by_pipeline_id + ) + end + end + end + def add_message(severity, content) messages.build(severity: severity, content: content) end diff --git a/app/models/personal_access_token.rb b/app/models/personal_access_token.rb index 68ba3d6eab4..31e5e6f73bf 100644 --- a/app/models/personal_access_token.rb +++ b/app/models/personal_access_token.rb @@ -33,6 +33,7 @@ class PersonalAccessToken < ApplicationRecord scope :preload_users, -> { preload(:user) } scope :order_expires_at_asc, -> { reorder(expires_at: :asc) } scope :order_expires_at_desc, -> { reorder(expires_at: :desc) } + scope :order_expires_at_asc_id_desc, -> { reorder(expires_at: :asc, id: :desc) } scope :project_access_token, -> { includes(:user).where(user: { user_type: :project_bot }) } scope :owner_is_human, -> { includes(:user).where(user: { user_type: :human }) } @@ -77,7 +78,8 @@ class PersonalAccessToken < ApplicationRecord super.merge( { 'expires_at_asc' => -> { order_expires_at_asc }, - 'expires_at_desc' => -> { order_expires_at_desc } + 'expires_at_desc' => -> { order_expires_at_desc }, + 'expires_at_asc_id_desc' => -> { order_expires_at_asc_id_desc } } ) end diff --git a/app/models/project.rb b/app/models/project.rb index c8d7afdd46f..39a7541e5d3 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1041,6 +1041,13 @@ class Project < ApplicationRecord def emails_enabled? !emails_disabled? end + + def cascade_cancel_pipelines_enabled? + strong_memoize(:cascade_cancel_pipelines_enabled) do + Feature.enabled?(:ci_parent_pipeline_cancels_children, self) + end + end + override :lfs_enabled? def lfs_enabled? return namespace.lfs_enabled? if self[:lfs_enabled].nil? diff --git a/app/serializers/group_access_token_entity.rb b/app/serializers/group_access_token_entity.rb new file mode 100644 index 00000000000..e832eef1188 --- /dev/null +++ b/app/serializers/group_access_token_entity.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +# rubocop: disable Gitlab/NamespacedClass +class GroupAccessTokenEntity < API::Entities::PersonalAccessToken + include Gitlab::Routing + + expose :revoke_path do |token, options| + group = options.fetch(:group) + + next unless group + + revoke_group_settings_access_token_path( + id: token, + group_id: group.path) + end + + expose :access_level do |token, options| + group = options.fetch(:group) + + next unless group + next unless token.user + + group.member(token.user)&.access_level + end +end +# rubocop: enable Gitlab/NamespacedClass diff --git a/app/serializers/group_access_token_serializer.rb b/app/serializers/group_access_token_serializer.rb new file mode 100644 index 00000000000..55f6de77844 --- /dev/null +++ b/app/serializers/group_access_token_serializer.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +# rubocop: disable Gitlab/NamespacedClass +class GroupAccessTokenSerializer < BaseSerializer + entity GroupAccessTokenEntity +end +# rubocop: enable Gitlab/NamespacedClass diff --git a/app/serializers/personal_access_token_entity.rb b/app/serializers/personal_access_token_entity.rb new file mode 100644 index 00000000000..acd06fecd12 --- /dev/null +++ b/app/serializers/personal_access_token_entity.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +# rubocop: disable Gitlab/NamespacedClass +class PersonalAccessTokenEntity < API::Entities::PersonalAccessToken + include Gitlab::Routing + + expose :revoke_path do |token, options| + revoke_profile_personal_access_token_path(token) + end +end +# rubocop: enable Gitlab/NamespacedClass diff --git a/app/serializers/personal_access_token_serializer.rb b/app/serializers/personal_access_token_serializer.rb new file mode 100644 index 00000000000..0a59fa117f9 --- /dev/null +++ b/app/serializers/personal_access_token_serializer.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +# rubocop: disable Gitlab/NamespacedClass +class PersonalAccessTokenSerializer < BaseSerializer + entity PersonalAccessTokenEntity +end +# rubocop: enable Gitlab/NamespacedClass diff --git a/app/serializers/project_access_token_entity.rb b/app/serializers/project_access_token_entity.rb new file mode 100644 index 00000000000..b317057c952 --- /dev/null +++ b/app/serializers/project_access_token_entity.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +# rubocop: disable Gitlab/NamespacedClass +class ProjectAccessTokenEntity < API::Entities::PersonalAccessToken + include Gitlab::Routing + + expose :revoke_path do |token, options| + project = options.fetch(:project) + + next unless project + + revoke_namespace_project_settings_access_token_path( + id: token, + namespace_id: project.namespace.path, + project_id: project.path) + end + + expose :access_level do |token, options| + project = options.fetch(:project) + + next unless project + next unless token.user + + project.member(token.user)&.access_level + end +end +# rubocop: enable Gitlab/NamespacedClass diff --git a/app/serializers/project_access_token_serializer.rb b/app/serializers/project_access_token_serializer.rb new file mode 100644 index 00000000000..97db088cf64 --- /dev/null +++ b/app/serializers/project_access_token_serializer.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +# rubocop: disable Gitlab/NamespacedClass +class ProjectAccessTokenSerializer < BaseSerializer + entity ProjectAccessTokenEntity +end +# rubocop: enable Gitlab/NamespacedClass diff --git a/app/services/ci/destroy_pipeline_service.rb b/app/services/ci/destroy_pipeline_service.rb index d85e52e1312..1c563396162 100644 --- a/app/services/ci/destroy_pipeline_service.rb +++ b/app/services/ci/destroy_pipeline_service.rb @@ -7,7 +7,7 @@ module Ci Ci::ExpirePipelineCacheService.new.execute(pipeline, delete: true) - pipeline.cancel_running if pipeline.cancelable? + pipeline.cancel_running(cascade_to_children: true, execute_async: false) if pipeline.cancelable? # The pipeline, the builds, job and pipeline artifacts all get destroyed here. # Ci::Pipeline#destroy triggers fast destroy on job_artifacts and diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml index a1a5248c060..22503531008 100644 --- a/app/workers/all_queues.yml +++ b/app/workers/all_queues.yml @@ -2109,6 +2109,15 @@ :weight: 2 :idempotent: false :tags: [] +- :name: ci_cancel_pipeline + :worker_name: Ci::CancelPipelineWorker + :feature_category: :continuous_integration + :has_external_dependencies: false + :urgency: :high + :resource_boundary: :unknown + :weight: 1 + :idempotent: true + :tags: [] - :name: ci_delete_objects :worker_name: Ci::DeleteObjectsWorker :feature_category: :continuous_integration diff --git a/app/workers/ci/cancel_pipeline_worker.rb b/app/workers/ci/cancel_pipeline_worker.rb new file mode 100644 index 00000000000..147839a0625 --- /dev/null +++ b/app/workers/ci/cancel_pipeline_worker.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Ci + class CancelPipelineWorker + include ApplicationWorker + + # lots of updates to ci_builds + data_consistency :always + feature_category :continuous_integration + idempotent! + deduplicate :until_executed + urgency :high + + def perform(pipeline_id, auto_canceled_by_pipeline_id) + ::Ci::Pipeline.find_by_id(pipeline_id).try do |pipeline| + pipeline.cancel_running( + # cascade_to_children is false because we iterate through children + # we also cancel bridges prior to prevent more children + cascade_to_children: false, + auto_canceled_by_pipeline_id: auto_canceled_by_pipeline_id + ) + end + end + end +end diff --git a/config/feature_flags/development/ci_parent_pipeline_cancels_children.yml b/config/feature_flags/development/ci_parent_pipeline_cancels_children.yml new file mode 100644 index 00000000000..0c8f722b4c1 --- /dev/null +++ b/config/feature_flags/development/ci_parent_pipeline_cancels_children.yml @@ -0,0 +1,8 @@ +--- +name: ci_parent_pipeline_cancels_children +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82149 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/354528 +milestone: '15.3' +type: development +group: group::pipeline execution +default_enabled: false diff --git a/config/metrics/aggregates/code_review.yml b/config/metrics/aggregates/code_review.yml index 2a58540f348..f1bf825bbd3 100644 --- a/config/metrics/aggregates/code_review.yml +++ b/config/metrics/aggregates/code_review.yml @@ -80,6 +80,12 @@ - 'i_code_review_user_create_note_in_ipynb_diff' - 'i_code_review_user_create_note_in_ipynb_diff_mr' - 'i_code_review_user_create_note_in_ipynb_diff_commit' + - 'i_code_review_merge_request_widget_test_summary_view' + - 'i_code_review_merge_request_widget_test_summary_full_report_clicked' + - 'i_code_review_merge_request_widget_test_summary_expand' + - 'i_code_review_merge_request_widget_test_summary_expand_success' + - 'i_code_review_merge_request_widget_test_summary_expand_warning' + - 'i_code_review_merge_request_widget_test_summary_expand_failed' - name: code_review_category_monthly_active_users operator: OR source: redis @@ -148,6 +154,12 @@ - 'i_code_review_user_create_note_in_ipynb_diff' - 'i_code_review_user_create_note_in_ipynb_diff_mr' - 'i_code_review_user_create_note_in_ipynb_diff_commit' + - 'i_code_review_merge_request_widget_test_summary_view' + - 'i_code_review_merge_request_widget_test_summary_full_report_clicked' + - 'i_code_review_merge_request_widget_test_summary_expand' + - 'i_code_review_merge_request_widget_test_summary_expand_success' + - 'i_code_review_merge_request_widget_test_summary_expand_warning' + - 'i_code_review_merge_request_widget_test_summary_expand_failed' - name: code_review_extension_category_monthly_active_users operator: OR source: redis diff --git a/config/metrics/counts_28d/20220708162311_i_code_review_merge_request_widget_test_summary_view_monthly.yml b/config/metrics/counts_28d/20220708162311_i_code_review_merge_request_widget_test_summary_view_monthly.yml new file mode 100644 index 00000000000..07ba085063a --- /dev/null +++ b/config/metrics/counts_28d/20220708162311_i_code_review_merge_request_widget_test_summary_view_monthly.yml @@ -0,0 +1,25 @@ +--- +key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_view_monthly +description: The count of unique users (monthly) who were able to see the Test Summary widget extension +product_section: dev +product_stage: create +product_group: code_review +product_category: code_review +value_type: number +status: active +milestone: "15.2" +introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831" +time_frame: 28d +data_source: redis_hll +data_category: optional +instrumentation_class: RedisHLLMetric +options: + events: + - i_code_review_merge_request_widget_test_summary_view +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/config/metrics/counts_28d/20220708163625_i_code_review_merge_request_widget_test_summary_full_report_clicked_monthly.yml b/config/metrics/counts_28d/20220708163625_i_code_review_merge_request_widget_test_summary_full_report_clicked_monthly.yml new file mode 100644 index 00000000000..1b27e018e5e --- /dev/null +++ b/config/metrics/counts_28d/20220708163625_i_code_review_merge_request_widget_test_summary_full_report_clicked_monthly.yml @@ -0,0 +1,25 @@ +--- +key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_full_report_clicked_monthly +description: The count of unique users (monthly) who clicked the Full Report button on the Test Summary widget extension +product_section: dev +product_stage: create +product_group: code_review +product_category: code_review +value_type: number +status: active +milestone: "15.2" +introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831" +time_frame: 28d +data_source: redis_hll +data_category: optional +instrumentation_class: RedisHLLMetric +options: + events: + - i_code_review_merge_request_widget_test_summary_full_report_clicked +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/config/metrics/counts_28d/20220708164545_i_code_review_merge_request_widget_test_summary_expand_monthly.yml b/config/metrics/counts_28d/20220708164545_i_code_review_merge_request_widget_test_summary_expand_monthly.yml new file mode 100644 index 00000000000..40134414c5b --- /dev/null +++ b/config/metrics/counts_28d/20220708164545_i_code_review_merge_request_widget_test_summary_expand_monthly.yml @@ -0,0 +1,25 @@ +--- +key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_expand_monthly +description: The count of unique users (monthly) who expanded the Test Summary widget extension +product_section: dev +product_stage: create +product_group: code_review +product_category: code_review +value_type: number +status: active +milestone: "15.2" +introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831" +time_frame: 28d +data_source: redis_hll +data_category: optional +instrumentation_class: RedisHLLMetric +options: + events: + - i_code_review_merge_request_widget_test_summary_expand +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/config/metrics/counts_28d/20220708165638_i_code_review_merge_request_widget_test_summary_expand_success_monthly.yml b/config/metrics/counts_28d/20220708165638_i_code_review_merge_request_widget_test_summary_expand_success_monthly.yml new file mode 100644 index 00000000000..a6c08e49a5b --- /dev/null +++ b/config/metrics/counts_28d/20220708165638_i_code_review_merge_request_widget_test_summary_expand_success_monthly.yml @@ -0,0 +1,25 @@ +--- +key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_expand_success_monthly +description: The count of unique users (monthly) who expanded the Test Summary widget extension while it is in its Success state +product_section: dev +product_stage: create +product_group: code_review +product_category: code_review +value_type: number +status: active +milestone: "15.2" +introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831" +time_frame: 28d +data_source: redis_hll +data_category: optional +instrumentation_class: RedisHLLMetric +options: + events: + - i_code_review_merge_request_widget_test_summary_expand_success +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/config/metrics/counts_28d/20220708170514_i_code_review_merge_request_widget_test_summary_expand_warning_monthly.yml b/config/metrics/counts_28d/20220708170514_i_code_review_merge_request_widget_test_summary_expand_warning_monthly.yml new file mode 100644 index 00000000000..7636ffae159 --- /dev/null +++ b/config/metrics/counts_28d/20220708170514_i_code_review_merge_request_widget_test_summary_expand_warning_monthly.yml @@ -0,0 +1,25 @@ +--- +key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_expand_warning_monthly +description: The count of unique users (monthly) who expanded the Test Summary widget extension while it is in its Warning state +product_section: dev +product_stage: create +product_group: code_review +product_category: code_review +value_type: number +status: active +milestone: "15.2" +introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831" +time_frame: 28d +data_source: redis_hll +data_category: optional +instrumentation_class: RedisHLLMetric +options: + events: + - i_code_review_merge_request_widget_test_summary_expand_warning +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/config/metrics/counts_28d/20220708173741_i_code_review_merge_request_widget_test_summary_expand_failed_monthly.yml b/config/metrics/counts_28d/20220708173741_i_code_review_merge_request_widget_test_summary_expand_failed_monthly.yml new file mode 100644 index 00000000000..7b84436ad57 --- /dev/null +++ b/config/metrics/counts_28d/20220708173741_i_code_review_merge_request_widget_test_summary_expand_failed_monthly.yml @@ -0,0 +1,25 @@ +--- +key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_expand_failed_monthly +description: The count of unique users (monthly) who expanded the Test Summary widget extension while it is in its Failed state +product_section: dev +product_stage: create +product_group: code_review +product_category: code_review +value_type: number +status: active +milestone: "15.2" +introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831" +time_frame: 28d +data_source: redis_hll +data_category: optional +instrumentation_class: RedisHLLMetric +options: + events: + - i_code_review_merge_request_widget_test_summary_expand_failed +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/config/metrics/counts_7d/20220708162305_i_code_review_merge_request_widget_test_summary_view_weekly.yml b/config/metrics/counts_7d/20220708162305_i_code_review_merge_request_widget_test_summary_view_weekly.yml new file mode 100644 index 00000000000..a1cf41b62f0 --- /dev/null +++ b/config/metrics/counts_7d/20220708162305_i_code_review_merge_request_widget_test_summary_view_weekly.yml @@ -0,0 +1,25 @@ +--- +key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_view_weekly +description: The count of unique users (weekly) who were able to see the Test Summary widget extension +product_section: dev +product_stage: create +product_group: code_review +product_category: code_review +value_type: number +status: active +milestone: "15.2" +introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831" +time_frame: 7d +data_source: redis_hll +data_category: optional +instrumentation_class: RedisHLLMetric +options: + events: + - i_code_review_merge_request_widget_test_summary_view +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/config/metrics/counts_7d/20220708163619_i_code_review_merge_request_widget_test_summary_full_report_clicked_weekly.yml b/config/metrics/counts_7d/20220708163619_i_code_review_merge_request_widget_test_summary_full_report_clicked_weekly.yml new file mode 100644 index 00000000000..73c5799d984 --- /dev/null +++ b/config/metrics/counts_7d/20220708163619_i_code_review_merge_request_widget_test_summary_full_report_clicked_weekly.yml @@ -0,0 +1,25 @@ +--- +key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_full_report_clicked_weekly +description: The count of unique users (weekly) who clicked the Full Report button on the Test Summary widget extension +product_section: dev +product_stage: create +product_group: code_review +product_category: code_review +value_type: number +status: active +milestone: "15.2" +introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831" +time_frame: 7d +data_source: redis_hll +data_category: optional +instrumentation_class: RedisHLLMetric +options: + events: + - i_code_review_merge_request_widget_test_summary_full_report_clicked +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/config/metrics/counts_7d/20220708164539_i_code_review_merge_request_widget_test_summary_expand_weekly.yml b/config/metrics/counts_7d/20220708164539_i_code_review_merge_request_widget_test_summary_expand_weekly.yml new file mode 100644 index 00000000000..a3616e92e6f --- /dev/null +++ b/config/metrics/counts_7d/20220708164539_i_code_review_merge_request_widget_test_summary_expand_weekly.yml @@ -0,0 +1,25 @@ +--- +key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_expand_weekly +description: The count of unique users (weekly) who expanded the Test Summary widget extension +product_section: dev +product_stage: create +product_group: code_review +product_category: code_review +value_type: number +status: active +milestone: "15.2" +introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831" +time_frame: 7d +data_source: redis_hll +data_category: optional +instrumentation_class: RedisHLLMetric +options: + events: + - i_code_review_merge_request_widget_test_summary_expand +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/config/metrics/counts_7d/20220708165632_i_code_review_merge_request_widget_test_summary_expand_success_weekly.yml b/config/metrics/counts_7d/20220708165632_i_code_review_merge_request_widget_test_summary_expand_success_weekly.yml new file mode 100644 index 00000000000..728ca303438 --- /dev/null +++ b/config/metrics/counts_7d/20220708165632_i_code_review_merge_request_widget_test_summary_expand_success_weekly.yml @@ -0,0 +1,25 @@ +--- +key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_expand_success_weekly +description: The count of unique users (weekly) who expanded the Test Summary widget extension while it is in its Success state +product_section: dev +product_stage: create +product_group: code_review +product_category: code_review +value_type: number +status: active +milestone: "15.2" +introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831" +time_frame: 7d +data_source: redis_hll +data_category: optional +instrumentation_class: RedisHLLMetric +options: + events: + - i_code_review_merge_request_widget_test_summary_expand_success +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/config/metrics/counts_7d/20220708170508_i_code_review_merge_request_widget_test_summary_expand_warning_weekly.yml b/config/metrics/counts_7d/20220708170508_i_code_review_merge_request_widget_test_summary_expand_warning_weekly.yml new file mode 100644 index 00000000000..70a2bab68d8 --- /dev/null +++ b/config/metrics/counts_7d/20220708170508_i_code_review_merge_request_widget_test_summary_expand_warning_weekly.yml @@ -0,0 +1,25 @@ +--- +key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_expand_warning_weekly +description: The count of unique users (weekly) who expanded the Test Summary widget extension while it is in its Warning state +product_section: dev +product_stage: create +product_group: code_review +product_category: code_review +value_type: number +status: active +milestone: "15.2" +introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831" +time_frame: 7d +data_source: redis_hll +data_category: optional +instrumentation_class: RedisHLLMetric +options: + events: + - i_code_review_merge_request_widget_test_summary_expand_warning +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/config/metrics/counts_7d/20220708173736_i_code_review_merge_request_widget_test_summary_expand_failed_weekly.yml b/config/metrics/counts_7d/20220708173736_i_code_review_merge_request_widget_test_summary_expand_failed_weekly.yml new file mode 100644 index 00000000000..a25ac7de33c --- /dev/null +++ b/config/metrics/counts_7d/20220708173736_i_code_review_merge_request_widget_test_summary_expand_failed_weekly.yml @@ -0,0 +1,25 @@ +--- +key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_expand_failed_weekly +description: The count of unique users (weekly) who expanded the Test Summary widget extension while it is in its Failed state +product_section: dev +product_stage: create +product_group: code_review +product_category: code_review +value_type: number +status: active +milestone: "15.2" +introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831" +time_frame: 7d +data_source: redis_hll +data_category: optional +instrumentation_class: RedisHLLMetric +options: + events: + - i_code_review_merge_request_widget_test_summary_expand_failed +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/config/metrics/counts_all/20220708154149_i_code_review_merge_request_widget_test_summary_count_view.yml b/config/metrics/counts_all/20220708154149_i_code_review_merge_request_widget_test_summary_count_view.yml new file mode 100644 index 00000000000..79d9f062999 --- /dev/null +++ b/config/metrics/counts_all/20220708154149_i_code_review_merge_request_widget_test_summary_count_view.yml @@ -0,0 +1,24 @@ +--- +key_path: counts.i_code_review_merge_request_widget_test_summary_count_view +description: Total number of times the Test Summary widget extension was viewed (rendered to the screen) +product_section: dev +product_stage: create +product_group: code_review +product_category: code_review +value_type: number +status: active +milestone: "15.2" +introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831" +time_frame: all +data_source: redis +data_category: optional +options: + events: + - i_code_review_merge_request_widget_test_summary_count_view +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/config/metrics/counts_all/20220708154156_i_code_review_merge_request_widget_test_summary_count_full_report_clicked.yml b/config/metrics/counts_all/20220708154156_i_code_review_merge_request_widget_test_summary_count_full_report_clicked.yml new file mode 100644 index 00000000000..b4887bbe219 --- /dev/null +++ b/config/metrics/counts_all/20220708154156_i_code_review_merge_request_widget_test_summary_count_full_report_clicked.yml @@ -0,0 +1,24 @@ +--- +key_path: counts.i_code_review_merge_request_widget_test_summary_count_full_report_clicked +description: Total number of times the Test Summary widget extension Full Report button was clicked +product_section: dev +product_stage: create +product_group: code_review +product_category: code_review +value_type: number +status: active +milestone: "15.2" +introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831" +time_frame: all +data_source: redis +data_category: optional +options: + events: + - i_code_review_merge_request_widget_test_summary_count_full_report_clicked +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/config/metrics/counts_all/20220708154201_i_code_review_merge_request_widget_test_summary_count_expand.yml b/config/metrics/counts_all/20220708154201_i_code_review_merge_request_widget_test_summary_count_expand.yml new file mode 100644 index 00000000000..1898fa971fa --- /dev/null +++ b/config/metrics/counts_all/20220708154201_i_code_review_merge_request_widget_test_summary_count_expand.yml @@ -0,0 +1,24 @@ +--- +key_path: counts.i_code_review_merge_request_widget_test_summary_count_expand +description: Total number of times the Test Summary widget extension was expanded (in any state) +product_section: dev +product_stage: create +product_group: code_review +product_category: code_review +value_type: number +status: active +milestone: "15.2" +introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831" +time_frame: all +data_source: redis +data_category: optional +options: + events: + - i_code_review_merge_request_widget_test_summary_count_expand +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/config/metrics/counts_all/20220708154206_i_code_review_merge_request_widget_test_summary_count_expand_success.yml b/config/metrics/counts_all/20220708154206_i_code_review_merge_request_widget_test_summary_count_expand_success.yml new file mode 100644 index 00000000000..91cd4d7a232 --- /dev/null +++ b/config/metrics/counts_all/20220708154206_i_code_review_merge_request_widget_test_summary_count_expand_success.yml @@ -0,0 +1,24 @@ +--- +key_path: counts.i_code_review_merge_request_widget_test_summary_count_expand_success +description: Total number of times the Test Summary widget extension was expanded (while in its Success state) +product_section: dev +product_stage: create +product_group: code_review +product_category: code_review +value_type: number +status: active +milestone: "15.2" +introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831" +time_frame: all +data_source: redis +data_category: optional +options: + events: + - i_code_review_merge_request_widget_test_summary_count_expand_success +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/config/metrics/counts_all/20220708154211_i_code_review_merge_request_widget_test_summary_count_expand_warning.yml b/config/metrics/counts_all/20220708154211_i_code_review_merge_request_widget_test_summary_count_expand_warning.yml new file mode 100644 index 00000000000..970d843c58e --- /dev/null +++ b/config/metrics/counts_all/20220708154211_i_code_review_merge_request_widget_test_summary_count_expand_warning.yml @@ -0,0 +1,24 @@ +--- +key_path: counts.i_code_review_merge_request_widget_test_summary_count_expand_warning +description: Total number of times the Test Summary widget extension was expanded (while in its Warning state) +product_section: dev +product_stage: create +product_group: code_review +product_category: code_review +value_type: number +status: active +milestone: "15.2" +introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831" +time_frame: all +data_source: redis +data_category: optional +options: + events: + - i_code_review_merge_request_widget_test_summary_count_expand_warning +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/config/metrics/counts_all/20220708154216_i_code_review_merge_request_widget_test_summary_count_expand_failed.yml b/config/metrics/counts_all/20220708154216_i_code_review_merge_request_widget_test_summary_count_expand_failed.yml new file mode 100644 index 00000000000..9b7c5c61602 --- /dev/null +++ b/config/metrics/counts_all/20220708154216_i_code_review_merge_request_widget_test_summary_count_expand_failed.yml @@ -0,0 +1,24 @@ +--- +key_path: counts.i_code_review_merge_request_widget_test_summary_count_expand_failed +description: Total number of times the Test Summary widget extension was expanded (while in its Failed state) +product_section: dev +product_stage: create +product_group: code_review +product_category: code_review +value_type: number +status: active +milestone: "15.2" +introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831" +time_frame: all +data_source: redis +data_category: optional +options: + events: + - i_code_review_merge_request_widget_test_summary_count_expand_failed +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml index ef57c86d324..73d0212b5fe 100644 --- a/config/sidekiq_queues.yml +++ b/config/sidekiq_queues.yml @@ -87,6 +87,8 @@ - 2 - - ci_batch_reset_minutes - 1 +- - ci_cancel_pipeline + - 1 - - ci_delete_objects - 1 - - ci_job_artifacts_expire_project_build_artifacts diff --git a/config/webpack.config.js b/config/webpack.config.js index 3c1d7cbf631..e9784ff0a48 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -473,9 +473,7 @@ module.exports = { new VueLoaderPlugin(), // automatically configure monaco editor web workers - new MonacoWebpackPlugin({ - globalAPI: true, - }), + new MonacoWebpackPlugin(), new GraphqlKnownOperationsPlugin({ filename: 'graphql_known_operations.yml' }), diff --git a/doc/.vale/gitlab/VersionTextSingleLine.yml b/doc/.vale/gitlab/VersionTextSingleLine.yml new file mode 100644 index 00000000000..f76574bcf8a --- /dev/null +++ b/doc/.vale/gitlab/VersionTextSingleLine.yml @@ -0,0 +1,13 @@ +--- +# Error: gitlab.VersionTextSingleLine +# +# Verifies that single-item version notes don't have a hyphen. +# +# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles +extends: existence +message: 'Version text with only a single item must not start with a hyphen.' +link: https://docs.gitlab.com/ee/development/documentation/versions.html#add-a-version-history-item +level: error +scope: raw +raw: + - '(\r|\n|\r\n){2}(> - .*)(\r|\n|\r\n){2}' diff --git a/doc/administration/audit_event_streaming.md b/doc/administration/audit_event_streaming.md index 82db1b41729..32214e6e5de 100644 --- a/doc/administration/audit_event_streaming.md +++ b/doc/administration/audit_event_streaming.md @@ -36,11 +36,6 @@ Users with at least the Owner role for a group can add event streaming destinati - When the destination list is not empty, select **{plus}** to show the section for adding destinations. 1. Enter the destination URL to add and select **Add**. -Event streaming is enabled if: - -- No warning is shown. -- The added endpoint is displayed in the UI. - ### Use the API To enable event streaming and add a destination, users with at least the Owner role for a group must use the @@ -120,11 +115,6 @@ Users with at least the Owner role for a group can delete event streaming destin 1. On the main area, select **Streams** tab. 1. Select **{remove}** at the right side of each item. -The external streaming destination is deleted when: - -- No warning is shown. -- The deleted endpoint is not displayed in the UI. - ### Use the API Delete an event streaming destination by specifying an ID. Get the required ID by @@ -237,11 +227,6 @@ Users with at least the Owner role for a group can add event streaming destinati [relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/361925). 1. Select **Save** to update the endpoint. -Event streaming is updated if: - -- The returned `errors` object is empty. -- The API responds with `200 OK`. - ### Deleting custom HTTP headers Deleting custom HTTP headers with the API or GitLab UI. @@ -281,11 +266,6 @@ Users with at least the Owner role for a group can delete event streaming destin 1. Select **{remove}** at the right side of the header. 1. Select **Save** to update the endpoint. -Event streaming is updated if: - -- The returned `errors` object is empty. -- The API responds with `200 OK`. - ### List all custom headers List all custom HTTP headers with the API or GitLab UI. diff --git a/doc/user/packages/package_registry/reduce_package_registry_storage.md b/doc/user/packages/package_registry/reduce_package_registry_storage.md index 4a03bd9e8a0..cd7dd062f60 100644 --- a/doc/user/packages/package_registry/reduce_package_registry_storage.md +++ b/doc/user/packages/package_registry/reduce_package_registry_storage.md @@ -53,7 +53,7 @@ The package files are permanently deleted. ## Cleanup policy -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/346153) in GitLab 15.2. +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/346153) in GitLab 15.2. Depending on the number of packages to remove, the process of manually deleting the packages can take a long time to finish. A cleanup policy defines a set of rules that, applied to a project, defines which package files you can automatically delete. diff --git a/jest.config.base.js b/jest.config.base.js index d4b1ace3b2c..5f6bf5d894f 100644 --- a/jest.config.base.js +++ b/jest.config.base.js @@ -149,6 +149,7 @@ module.exports = (path, options = {}) => { 'fault', 'dateformat', 'lowlight', + 'vscode-languageserver-types', ...gfmParserDependencies, ]; diff --git a/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb b/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb index f637001f9f8..9c12d46cede 100644 --- a/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb +++ b/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb @@ -40,7 +40,13 @@ module Gitlab ::Ci::Pipeline .id_in(pipeline_ids) .with_only_interruptible_builds - .each { |cancelable| cancelable.auto_cancel_running(pipeline) } + .each do |cancelable_pipeline| + # cascade_to_children not needed because we iterate through descendants here + cancelable_pipeline.cancel_running( + auto_canceled_by_pipeline_id: pipeline.id, + cascade_to_children: false + ) + end end end end diff --git a/lib/gitlab/memory/watchdog.rb b/lib/gitlab/memory/watchdog.rb index db75ba8a47d..722c8b5a001 100644 --- a/lib/gitlab/memory/watchdog.rb +++ b/lib/gitlab/memory/watchdog.rb @@ -167,15 +167,13 @@ module Gitlab end def init_prometheus_metrics(max_heap_fragmentation) - default_labels = { pid: worker_id } - @heap_frag_limit = Gitlab::Metrics.gauge( :gitlab_memwd_heap_frag_limit, - 'The configured limit for how fragmented the Ruby heap is allowed to be', - default_labels + 'The configured limit for how fragmented the Ruby heap is allowed to be' ) @heap_frag_limit.set({}, max_heap_fragmentation) + default_labels = { pid: worker_id } @heap_frag_violations = Gitlab::Metrics.counter( :gitlab_memwd_heap_frag_violations_total, 'Total number of times heap fragmentation in a Ruby process exceeded its allowed maximum', diff --git a/lib/gitlab/sidekiq_logging/logs_jobs.rb b/lib/gitlab/sidekiq_logging/logs_jobs.rb index de08de6632b..3e6e6e05e95 100644 --- a/lib/gitlab/sidekiq_logging/logs_jobs.rb +++ b/lib/gitlab/sidekiq_logging/logs_jobs.rb @@ -12,7 +12,6 @@ module Gitlab # Error information from the previous try is in the payload for # displaying in the Sidekiq UI, but is very confusing in logs! job = job.except( - 'error_backtrace', 'error_class', 'error_message', 'exception.backtrace', 'exception.class', 'exception.message', 'exception.sql' ) diff --git a/lib/gitlab/usage_data_counters.rb b/lib/gitlab/usage_data_counters.rb index 2a3dcf267c6..224897ed758 100644 --- a/lib/gitlab/usage_data_counters.rb +++ b/lib/gitlab/usage_data_counters.rb @@ -16,7 +16,8 @@ module Gitlab DesignsCounter, KubernetesAgentCounter, DiffsCounter, - ServiceUsageDataCounter + ServiceUsageDataCounter, + MergeRequestWidgetExtensionCounter ].freeze UsageDataCounterError = Class.new(StandardError) diff --git a/lib/gitlab/usage_data_counters/known_events/code_review_events.yml b/lib/gitlab/usage_data_counters/known_events/code_review_events.yml index 267b7fe673d..9e7f5487d1a 100644 --- a/lib/gitlab/usage_data_counters/known_events/code_review_events.yml +++ b/lib/gitlab/usage_data_counters/known_events/code_review_events.yml @@ -299,3 +299,29 @@ redis_slot: code_review category: code_review aggregation: weekly +# MR Widget Extensions +## Test Summary +- name: i_code_review_merge_request_widget_test_summary_view + redis_slot: code_review + category: code_review + aggregation: weekly +- name: i_code_review_merge_request_widget_test_summary_full_report_clicked + redis_slot: code_review + category: code_review + aggregation: weekly +- name: i_code_review_merge_request_widget_test_summary_expand + redis_slot: code_review + category: code_review + aggregation: weekly +- name: i_code_review_merge_request_widget_test_summary_expand_success + redis_slot: code_review + category: code_review + aggregation: weekly +- name: i_code_review_merge_request_widget_test_summary_expand_warning + redis_slot: code_review + category: code_review + aggregation: weekly +- name: i_code_review_merge_request_widget_test_summary_expand_failed + redis_slot: code_review + category: code_review + aggregation: weekly diff --git a/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb b/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb new file mode 100644 index 00000000000..5b42589cced --- /dev/null +++ b/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Gitlab + module UsageDataCounters + class MergeRequestWidgetExtensionCounter < BaseCounter + KNOWN_EVENTS = %w[view full_report_clicked expand expand_success expand_warning expand_failed].freeze + PREFIX = 'i_code_review_merge_request_widget' + WIDGETS = %w[test_summary].freeze + + class << self + private + + def known_events + self::WIDGETS.product(self::KNOWN_EVENTS).map { |name_parts| name_parts.join('_count_') } + end + end + end + end +end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 4a906868b5a..422b2f3dbac 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -5364,9 +5364,18 @@ msgstr "" msgid "AuditStreams|Setup streaming for audit events" msgstr "" +msgid "AuditStreams|Stream added successfully" +msgstr "" + msgid "AuditStreams|Stream count icon" msgstr "" +msgid "AuditStreams|Stream deleted successfully" +msgstr "" + +msgid "AuditStreams|Stream updated successfully" +msgstr "" + msgid "AuditStreams|Streams" msgstr "" @@ -23489,6 +23498,9 @@ msgstr "" msgid "LinkedResources|Cancel" msgstr "" +msgid "LinkedResources|Error deleting the linked resource for the incident: %{error}" +msgstr "" + msgid "LinkedResources|Fetching linked resources" msgstr "" @@ -23504,6 +23516,9 @@ msgstr "" msgid "LinkedResources|Remove" msgstr "" +msgid "LinkedResources|Something went wrong while deleting the linked resource for the incident." +msgstr "" + msgid "LinkedResources|Something went wrong while fetching linked resources for the incident." msgstr "" diff --git a/package.json b/package.json index 0ea8b8f3cda..dfc95d62278 100644 --- a/package.json +++ b/package.json @@ -140,9 +140,9 @@ "mermaid": "^9.1.1", "micromatch": "^4.0.5", "minimatch": "^3.0.4", - "monaco-editor": "^0.25.2", - "monaco-editor-webpack-plugin": "^4.0.0", - "monaco-yaml": "^2.5.1", + "monaco-editor": "^0.28.0", + "monaco-editor-webpack-plugin": "^4.2.0", + "monaco-yaml": "3.0.0", "mousetrap": "1.6.5", "papaparse": "^5.3.1", "patch-package": "^6.4.7", diff --git a/security.txt b/security.txt index f7adb43fda6..f19a0b6283d 100644 --- a/security.txt +++ b/security.txt @@ -1,6 +1,16 @@ -Contact: security@gitlab.com +# Preferred disclosure is via HackerOne +Contact: https://hackerone.com/gitlab/ +# Additional disclosure processes are available in our handbook: +Contact: https://about.gitlab.com/security/disclosure/ + +Policy: https://hackerone.com/gitlab/ + +Acknowledgments: https://hackerone.com/gitlab/ Acknowledgments: https://about.gitlab.com/security/vulnerability-acknowledgements/ + +Canonical: https://gitlab.com/gitlab-org/gitlab/-/blob/master/security.txt + Preferred-Languages: en -Canonical: https://about.gitlab.com/security/disclosure/ -Policy: https://hackerone.com/gitlab Hiring: https://about.gitlab.com/jobs/ + +Expires: 2023-07-31T00:00:00Z diff --git a/spec/controllers/profiles/personal_access_tokens_controller_spec.rb b/spec/controllers/profiles/personal_access_tokens_controller_spec.rb index aafea0050d3..0e531dbaf4b 100644 --- a/spec/controllers/profiles/personal_access_tokens_controller_spec.rb +++ b/spec/controllers/profiles/personal_access_tokens_controller_spec.rb @@ -87,6 +87,38 @@ RSpec.describe Profiles::PersonalAccessTokensController do end end + context "tokens returned are ordered" do + let(:expires_1_day_from_now) { 1.day.from_now.to_date } + let(:expires_2_day_from_now) { 2.days.from_now.to_date } + + before do + create(:personal_access_token, user: user, name: "Token1", expires_at: expires_1_day_from_now) + create(:personal_access_token, user: user, name: "Token2", expires_at: expires_2_day_from_now) + end + + it "orders token list ascending on expires_at" do + get :index + + first_token = assigns(:active_personal_access_tokens).first.as_json + expect(first_token[:name]).to eq("Token1") + expect(first_token[:expires_at]).to eq(expires_1_day_from_now.strftime("%Y-%m-%d")) + end + + it "orders tokens on id in case token has same expires_at" do + create(:personal_access_token, user: user, name: "Token3", expires_at: expires_1_day_from_now) + + get :index + + first_token = assigns(:active_personal_access_tokens).first.as_json + expect(first_token[:name]).to eq("Token3") + expect(first_token[:expires_at]).to eq(expires_1_day_from_now.strftime("%Y-%m-%d")) + + second_token = assigns(:active_personal_access_tokens).second.as_json + expect(second_token[:name]).to eq("Token1") + expect(second_token[:expires_at]).to eq(expires_1_day_from_now.strftime("%Y-%m-%d")) + end + end + context "access_token_pagination feature flag is disabled" do before do stub_feature_flags(access_token_pagination: false) diff --git a/spec/features/merge_request/maintainer_edits_fork_spec.rb b/spec/features/merge_request/maintainer_edits_fork_spec.rb index a98bfd1c8a4..39d948bb6fb 100644 --- a/spec/features/merge_request/maintainer_edits_fork_spec.rb +++ b/spec/features/merge_request/maintainer_edits_fork_spec.rb @@ -3,6 +3,7 @@ require 'spec_helper' RSpec.describe 'a maintainer edits files on a source-branch of an MR from a fork', :js, :sidekiq_might_not_need_inline do + include Spec::Support::Helpers::Features::SourceEditorSpecHelpers include ProjectForksHelper let(:user) { create(:user, username: 'the-maintainer') } let(:target_project) { create(:project, :public, :repository) } @@ -40,12 +41,13 @@ RSpec.describe 'a maintainer edits files on a source-branch of an MR from a fork end it 'allows committing to the source branch' do - execute_script("monaco.editor.getModels()[0].setValue('Updated the readme')") + content = 'Updated the readme' + editor_set_value(content) click_button 'Commit changes' wait_for_requests expect(page).to have_content('Your changes have been successfully committed') - expect(page).to have_content('Updated the readme') + expect(page).to have_content(content) end end diff --git a/spec/features/projects/blobs/edit_spec.rb b/spec/features/projects/blobs/edit_spec.rb index 54176378de8..f198a1f42e2 100644 --- a/spec/features/projects/blobs/edit_spec.rb +++ b/spec/features/projects/blobs/edit_spec.rb @@ -3,6 +3,7 @@ require 'spec_helper' RSpec.describe 'Editing file blob', :js do + include Spec::Support::Helpers::Features::SourceEditorSpecHelpers include TreeHelper include BlobSpecHelpers @@ -42,7 +43,7 @@ RSpec.describe 'Editing file blob', :js do def fill_editor(content: 'class NextFeature\\nend\\n') wait_for_requests - execute_script("monaco.editor.getModels()[0].setValue('#{content}')") + editor_set_value(content) end context 'from MR diff' do @@ -98,10 +99,8 @@ RSpec.describe 'Editing file blob', :js do click_link 'Preview changes' wait_for_requests - old_line_count = page.all('.line_holder.old').size new_line_count = page.all('.line_holder.new').size - expect(old_line_count).to be > 0 expect(new_line_count).to be > 0 end end diff --git a/spec/features/projects/ci/lint_spec.rb b/spec/features/projects/ci/lint_spec.rb index 7f10c6afcd5..8b0a2f81865 100644 --- a/spec/features/projects/ci/lint_spec.rb +++ b/spec/features/projects/ci/lint_spec.rb @@ -26,6 +26,7 @@ RSpec.describe 'CI Lint', :js do shared_examples 'validates the YAML' do before do click_on 'Validate' + scroll_to(page.find('[data-testid="ci-lint-status"]')) end context 'YAML is correct' do diff --git a/spec/features/projects/files/user_creates_files_spec.rb b/spec/features/projects/files/user_creates_files_spec.rb index 7344c91b6dc..a81f31d663e 100644 --- a/spec/features/projects/files/user_creates_files_spec.rb +++ b/spec/features/projects/files/user_creates_files_spec.rb @@ -3,6 +3,7 @@ require 'spec_helper' RSpec.describe 'Projects > Files > User creates files', :js do + include Spec::Support::Helpers::Features::SourceEditorSpecHelpers include BlobSpecHelpers let(:fork_message) do @@ -89,8 +90,7 @@ RSpec.describe 'Projects > Files > User creates files', :js do end it 'creates and commit a new file' do - find('#editor') - execute_script("monaco.editor.getModels()[0].setValue('*.rbca')") + editor_set_value('*.rbca') fill_in(:file_name, with: 'not_a_file.md') fill_in(:commit_message, with: 'New commit message', visible: true) click_button('Commit changes') @@ -107,8 +107,7 @@ RSpec.describe 'Projects > Files > User creates files', :js do it 'creates and commit a new file with new lines at the end of file' do set_default_button('edit') - find('#editor') - execute_script('monaco.editor.getModels()[0].setValue("Sample\n\n\n")') + editor_set_value('Sample\n\n\n') fill_in(:file_name, with: 'not_a_file.md') fill_in(:commit_message, with: 'New commit message', visible: true) click_button('Commit changes') @@ -119,8 +118,7 @@ RSpec.describe 'Projects > Files > User creates files', :js do click_link('Edit') - find('#editor') - expect(evaluate_script('monaco.editor.getModels()[0].getValue()')).to eq("Sample\n\n\n") + expect(find('.monaco-editor')).to have_content('Sample\n\n\n') end it 'creates and commit a new file with a directory name' do @@ -128,8 +126,7 @@ RSpec.describe 'Projects > Files > User creates files', :js do expect(page).to have_selector('.file-editor') - find('#editor') - execute_script("monaco.editor.getModels()[0].setValue('*.rbca')") + editor_set_value('*.rbca') fill_in(:commit_message, with: 'New commit message', visible: true) click_button('Commit changes') @@ -143,8 +140,7 @@ RSpec.describe 'Projects > Files > User creates files', :js do it 'creates and commit a new file specifying a new branch' do expect(page).to have_selector('.file-editor') - find('#editor') - execute_script("monaco.editor.getModels()[0].setValue('*.rbca')") + editor_set_value('*.rbca') fill_in(:file_name, with: 'not_a_file.md') fill_in(:commit_message, with: 'New commit message', visible: true) fill_in(:branch_name, with: 'new_branch_name', visible: true) @@ -178,8 +174,7 @@ RSpec.describe 'Projects > Files > User creates files', :js do it 'creates and commit new file in forked project' do expect(page).to have_selector('.file-editor') - find('#editor') - execute_script("monaco.editor.getModels()[0].setValue('*.rbca')") + editor_set_value('*.rbca') fill_in(:file_name, with: 'not_a_file.md') fill_in(:commit_message, with: 'New commit message', visible: true) diff --git a/spec/features/projects/files/user_edits_files_spec.rb b/spec/features/projects/files/user_edits_files_spec.rb index 1ac45970828..d7460538be9 100644 --- a/spec/features/projects/files/user_edits_files_spec.rb +++ b/spec/features/projects/files/user_edits_files_spec.rb @@ -3,6 +3,7 @@ require 'spec_helper' RSpec.describe 'Projects > Files > User edits files', :js do + include Spec::Support::Helpers::Features::SourceEditorSpecHelpers include ProjectForksHelper include BlobSpecHelpers @@ -50,10 +51,9 @@ RSpec.describe 'Projects > Files > User edits files', :js do click_link_or_button('Edit') find('.file-editor', match: :first) - find('#editor') - set_editor_value('*.rbca') + editor_set_value('*.rbca') - expect(editor_value).to eq('*.rbca') + expect(find('.monaco-editor')).to have_content('*.rbca') end it 'does not show the edit link if a file is binary' do @@ -72,8 +72,7 @@ RSpec.describe 'Projects > Files > User edits files', :js do click_link_or_button('Edit') find('.file-editor', match: :first) - find('#editor') - set_editor_value('*.rbca') + editor_set_value('*.rbca') fill_in(:commit_message, with: 'New commit message', visible: true) click_button('Commit changes') @@ -91,8 +90,7 @@ RSpec.describe 'Projects > Files > User edits files', :js do find('.file-editor', match: :first) - find('#editor') - set_editor_value('*.rbca') + editor_set_value('*.rbca') fill_in(:commit_message, with: 'New commit message', visible: true) fill_in(:branch_name, with: 'new_branch_name', visible: true) click_button('Commit changes') @@ -110,8 +108,7 @@ RSpec.describe 'Projects > Files > User edits files', :js do click_link_or_button('Edit') find('.file-editor', match: :first) - find('#editor') - set_editor_value('*.rbca') + editor_set_value('*.rbca') click_link('Preview changes') expect(page).to have_css('.line_holder.new') @@ -156,10 +153,9 @@ RSpec.describe 'Projects > Files > User edits files', :js do find('.file-editor', match: :first) - find('#editor') - set_editor_value('*.rbca') + editor_set_value('*.rbca') - expect(editor_value).to eq('*.rbca') + expect(find('.monaco-editor')).to have_content('*.rbca') end it 'opens the Web IDE in a forked project', :sidekiq_might_not_need_inline do @@ -187,8 +183,7 @@ RSpec.describe 'Projects > Files > User edits files', :js do find('.file-editor', match: :first) - find('#editor') - set_editor_value('*.rbca') + editor_set_value('*.rbca') fill_in(:commit_message, with: 'New commit message', visible: true) click_button('Commit changes') @@ -216,8 +211,7 @@ RSpec.describe 'Projects > Files > User edits files', :js do expect(page).not_to have_link('Fork') - find('#editor') - set_editor_value('*.rbca') + editor_set_value('*.rbca') fill_in(:commit_message, with: 'Another commit', visible: true) click_button('Commit changes') diff --git a/spec/frontend/__mocks__/monaco-editor/index.js b/spec/frontend/__mocks__/monaco-editor/index.js index 18b7df32f9b..384f9993150 100644 --- a/spec/frontend/__mocks__/monaco-editor/index.js +++ b/spec/frontend/__mocks__/monaco-editor/index.js @@ -15,4 +15,3 @@ jest.mock('monaco-editor/esm/vs/language/typescript/tsMode'); jest.mock('monaco-yaml/lib/esm/yamlMode'); export * from 'monaco-editor/esm/vs/editor/editor.api'; -export default global.monaco; diff --git a/spec/frontend/editor/source_editor_spec.js b/spec/frontend/editor/source_editor_spec.js index 74aae7b899b..6a8e7b296aa 100644 --- a/spec/frontend/editor/source_editor_spec.js +++ b/spec/frontend/editor/source_editor_spec.js @@ -267,7 +267,6 @@ describe('Base editor', () => { let editorEl2; let inst1; let inst2; - const readOnlyIndex = '78'; // readOnly option has the internal index of 78 in the editor's options beforeEach(() => { setHTMLFixture('
'); @@ -331,10 +330,10 @@ describe('Base editor', () => { }); inst1 = editor.createInstance(inst1Args); - expect(inst1.getOption(readOnlyIndex)).toBe(true); + expect(inst1.getRawOptions().readOnly).toBe(true); inst2 = editor.createInstance(inst2Args); - expect(inst2.getOption(readOnlyIndex)).toBe(true); + expect(inst2.getRawOptions().readOnly).toBe(true); }); it('allows overriding editor options on the instance level', () => { @@ -346,7 +345,7 @@ describe('Base editor', () => { readOnly: false, }); - expect(inst1.getOption(readOnlyIndex)).toBe(false); + expect(inst1.getRawOptions().readOnly).toBe(false); }); it('disposes instances and relevant models independently from each other', () => { diff --git a/spec/frontend/environment.js b/spec/frontend/environment.js index dc1c1dfbe4a..1c84350bd8e 100644 --- a/spec/frontend/environment.js +++ b/spec/frontend/environment.js @@ -70,7 +70,6 @@ class CustomEnvironment extends JSDOMEnvironment { // // Monaco-related environment variables // - this.global.MonacoEnvironment = { globalAPI: true }; Object.defineProperty(this.global, 'matchMedia', { writable: true, value: (query) => ({ diff --git a/spec/frontend/ide/components/repo_editor_spec.js b/spec/frontend/ide/components/repo_editor_spec.js index 7a0bcda1b7a..e81f68ce626 100644 --- a/spec/frontend/ide/components/repo_editor_spec.js +++ b/spec/frontend/ide/components/repo_editor_spec.js @@ -145,8 +145,7 @@ describe('RepoEditor', () => { jest.clearAllMocks(); // create a new model each time, otherwise tests conflict with each other // because of same model being used in multiple tests - // eslint-disable-next-line no-undef - monaco.editor.getModels().forEach((model) => model.dispose()); + monacoEditor.getModels().forEach((model) => model.dispose()); wrapper.destroy(); wrapper = null; }); diff --git a/spec/frontend_integration/ide/helpers/start.js b/spec/frontend_integration/ide/helpers/start.js index 3c5ed9dfe20..925db12f36e 100644 --- a/spec/frontend_integration/ide/helpers/start.js +++ b/spec/frontend_integration/ide/helpers/start.js @@ -1,5 +1,4 @@ -/* global monaco */ - +import { editor as monacoEditor } from 'monaco-editor'; import setWindowLocation from 'helpers/set_window_location_helper'; import { TEST_HOST } from 'helpers/test_constants'; import { initIde } from '~/ide'; @@ -20,7 +19,7 @@ export default (container, { isRepoEmpty = false, path = '', mrId = '' } = {}) = const vm = initIde(el, { extendStore }); // We need to dispose of editor Singleton things or tests will bump into eachother - vm.$on('destroy', () => monaco.editor.getModels().forEach((model) => model.dispose())); + vm.$on('destroy', () => monacoEditor.getModels().forEach((model) => model.dispose())); return vm; }; diff --git a/spec/lib/gitlab/memory/watchdog_spec.rb b/spec/lib/gitlab/memory/watchdog_spec.rb index 8b82078bcb9..f9e6b698cda 100644 --- a/spec/lib/gitlab/memory/watchdog_spec.rb +++ b/spec/lib/gitlab/memory/watchdog_spec.rb @@ -26,6 +26,8 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures, :prometheus do allow(logger).to receive(:info) allow(Gitlab::Metrics::Memory).to receive(:gc_heap_fragmentation).and_return(fragmentation) + + allow(::Prometheus::PidProvider).to receive(:worker_id).and_return('worker_1') end after do @@ -37,7 +39,7 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures, :prometheus do let(:max_strikes) { 0 } it 'sets the heap fragmentation limit gauge' do - allow(Gitlab::Metrics).to receive(:gauge).and_return(heap_frag_limit_gauge) + allow(Gitlab::Metrics).to receive(:gauge).with(anything, anything).and_return(heap_frag_limit_gauge) expect(heap_frag_limit_gauge).to receive(:set).with({}, max_heap_fragmentation) end @@ -86,11 +88,12 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures, :prometheus do let(:fragmentation) { max_heap_fragmentation + 0.1 } before do + expected_labels = { pid: 'worker_1' } allow(Gitlab::Metrics).to receive(:counter) - .with(:gitlab_memwd_heap_frag_violations_total, anything, anything) + .with(:gitlab_memwd_heap_frag_violations_total, anything, expected_labels) .and_return(heap_frag_violations_counter) allow(Gitlab::Metrics).to receive(:counter) - .with(:gitlab_memwd_heap_frag_violations_handled_total, anything, anything) + .with(:gitlab_memwd_heap_frag_violations_handled_total, anything, expected_labels) .and_return(heap_frag_violations_handled_counter) allow(heap_frag_violations_counter).to receive(:increment) allow(heap_frag_violations_handled_counter).to receive(:increment) @@ -146,7 +149,6 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures, :prometheus do end it 'logs the event' do - expect(::Prometheus::PidProvider).to receive(:worker_id).at_least(:once).and_return('worker_1') expect(Gitlab::Metrics::System).to receive(:memory_usage_rss).at_least(:once).and_return(1024) expect(logger).to receive(:warn).with({ message: 'heap fragmentation limit exceeded', diff --git a/spec/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter_spec.rb new file mode 100644 index 00000000000..e073fac504a --- /dev/null +++ b/spec/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter_spec.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::UsageDataCounters::MergeRequestWidgetExtensionCounter do + it_behaves_like 'a redis usage counter', 'Widget Extension', :test_summary_count_expand + + it_behaves_like 'a redis usage counter with totals', :i_code_review_merge_request_widget, test_summary_count_expand: 5 +end diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index b1ddc26b1dc..6ed92c4196f 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -2920,7 +2920,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#cancel_running' do - subject(:latest_status) { pipeline.statuses.pluck(:status) } + let(:latest_status) { pipeline.statuses.pluck(:status) } let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) } @@ -2963,6 +2963,32 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end end + context 'with bridge jobs' do + before do + create(:ci_bridge, :created, pipeline: pipeline) + + pipeline.cancel_running + end + + it 'bridges are canceled' do + expect(pipeline.bridges.first.status).to eq 'canceled' + end + end + + context 'when pipeline is not cancelable' do + before do + create(:ci_build, :canceled, stage_idx: 0, pipeline: pipeline) + + pipeline.cancel_running + end + + it 'does not send cancel signal to cancel self' do + expect(pipeline).not_to receive(:cancel_self_only) + + pipeline.cancel_running + end + end + context 'preloading relations' do let(:pipeline1) { create(:ci_empty_pipeline, :created) } let(:pipeline2) { create(:ci_empty_pipeline, :created) } @@ -2994,37 +3020,257 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end end - context 'when the first try cannot get an exclusive lock' do - let(:retries) { 1 } + shared_examples 'retries' do + context 'when the first try cannot get an exclusive lock' do + let(:retries) { 1 } - subject(:cancel_running) { pipeline.cancel_running(retries: retries) } + subject { pipeline.cancel_running(retries: retries) } - before do - build = create(:ci_build, :running, pipeline: pipeline) + before do + create(:ci_build, :running, pipeline: pipeline) - allow(pipeline.cancelable_statuses).to receive(:find_in_batches).and_yield([build]) + stub_first_cancel_call_fails + end - call_count = 0 - allow(build).to receive(:cancel).and_wrap_original do |original, *args| - call_count >= retries ? raise(ActiveRecord::StaleObjectError) : original.call(*args) + it 'retries again and cancels the build' do + subject - call_count += 1 + expect(latest_status).to contain_exactly('canceled') + end + + context 'when the retries parameter is 0' do + let(:retries) { 0 } + + it 'raises error' do + expect { subject }.to raise_error(ActiveRecord::StaleObjectError) + end end end - it 'retries again and cancels the build' do - cancel_running + def stub_first_cancel_call_fails + call_count = 0 - expect(latest_status).to contain_exactly('canceled') + allow_next_found_instance_of(Ci::Build) do |build| + allow(build).to receive(:cancel).and_wrap_original do |original, *args| # rubocop:disable RSpec/AnyInstanceOf + call_count >= retries ? raise(ActiveRecord::StaleObjectError) : original.call(*args) + + call_count += 1 + end + end + end + end + + context 'with retries' do + context 'when feature ci_parent_pipeline_cancels_children is disabled' do + before do + stub_feature_flags(ci_parent_pipeline_cancels_children: false) + end + + it_behaves_like 'retries' end - context 'when the retries parameter is 0' do - let(:retries) { 0 } + context 'when feature ci_parent_pipeline_cancels_children is enabled' do + it_behaves_like 'retries' + end + end - it 'raises error' do - expect do + context 'when auto canceled' do + let!(:canceled_by) { create(:ci_empty_pipeline) } + + before do + create(:ci_build, :running, pipeline: pipeline) + + pipeline.cancel_running(auto_canceled_by_pipeline_id: canceled_by.id) + end + + it 'sets auto cancel' do + jobs_canceled_by = pipeline.statuses.map { |s| s.auto_canceled_by.id } + + expect(jobs_canceled_by).to contain_exactly(canceled_by.id) + expect(pipeline.auto_canceled_by.id).to eq(canceled_by.id) + end + end + + context 'when there are child pipelines', :sidekiq_inline do + let_it_be(:child_pipeline) { create(:ci_empty_pipeline, :created, child_of: pipeline) } + + before do + project.clear_memoization(:cascade_cancel_pipelines_enabled) + + pipeline.reload + end + + context 'when cascade_to_children is true' do + let(:cascade_to_children) { true } + let(:canceled_by) { nil } + let(:execute_async) { true } + + let(:params) do + { + cascade_to_children: cascade_to_children, + execute_async: execute_async + }.tap do |p| + p.merge!(auto_canceled_by_pipeline_id: canceled_by.id) if canceled_by + end + end + + subject(:cancel_running) { pipeline.cancel_running(**params) } + + context 'when cancelable child pipeline builds' do + before do + create(:ci_build, :created, pipeline: child_pipeline) + create(:ci_build, :running, pipeline: child_pipeline) + end + + it 'cancels child builds' do cancel_running - end.to raise_error(ActiveRecord::StaleObjectError) + + latest_status_for_child = child_pipeline.statuses.pluck(:status) + expect(latest_status_for_child).to eq %w(canceled canceled) + expect(latest_status).to eq %w(canceled) + end + + it 'cancels bridges' do + create(:ci_bridge, :created, pipeline: pipeline) + create(:ci_bridge, :created, pipeline: child_pipeline) + + cancel_running + + expect(pipeline.bridges.reload.first.status).to eq 'canceled' + expect(child_pipeline.bridges.reload.first.status).to eq 'canceled' + end + + context 'with nested child pipelines' do + let!(:nested_child_pipeline) { create(:ci_empty_pipeline, :created, child_of: child_pipeline) } + let!(:nested_child_pipeline_build) { create(:ci_build, :created, pipeline: nested_child_pipeline) } + + it 'cancels them' do + cancel_running + + expect(nested_child_pipeline.reload.status).to eq 'canceled' + expect(nested_child_pipeline_build.reload.status).to eq 'canceled' + end + end + + context 'when auto canceled' do + let(:canceled_by) { create(:ci_empty_pipeline) } + + it 'sets auto cancel' do + cancel_running + + pipeline.reload + + jobs_canceled_by_ids = pipeline.statuses.map(&:auto_canceled_by_id) + child_pipelines_canceled_by_ids = pipeline.child_pipelines.map(&:auto_canceled_by_id) + child_pipelines_jobs_canceled_by_ids = pipeline.child_pipelines.map(&:statuses).flatten.map(&:auto_canceled_by_id) + + expect(jobs_canceled_by_ids).to contain_exactly(canceled_by.id) + expect(pipeline.auto_canceled_by_id).to eq(canceled_by.id) + expect(child_pipelines_canceled_by_ids).to contain_exactly(canceled_by.id) + expect(child_pipelines_jobs_canceled_by_ids).to contain_exactly(canceled_by.id, canceled_by.id) + end + end + + context 'when execute_async is false' do + let(:execute_async) { false } + + it 'runs sync' do + expect(::Ci::CancelPipelineWorker).not_to receive(:perform_async) + + cancel_running + end + + it 'cancels children' do + cancel_running + + latest_status_for_child = child_pipeline.statuses.pluck(:status) + expect(latest_status_for_child).to eq %w(canceled canceled) + expect(latest_status).to eq %w(canceled) + end + + context 'with nested child pipelines' do + let!(:nested_child_pipeline) { create(:ci_empty_pipeline, :created, child_of: child_pipeline) } + let!(:nested_child_pipeline_build) { create(:ci_build, :created, pipeline: nested_child_pipeline) } + + it 'cancels them' do + cancel_running + + expect(nested_child_pipeline.reload.status).to eq 'canceled' + expect(nested_child_pipeline_build.reload.status).to eq 'canceled' + end + end + end + end + + it 'does not cancel uncancelable child pipeline builds' do + create(:ci_build, :failed, pipeline: child_pipeline) + + cancel_running + + latest_status_for_child = child_pipeline.statuses.pluck(:status) + expect(latest_status_for_child).to eq %w(failed) + expect(latest_status).to eq %w(canceled) + end + + context 'when feature ci_parent_pipeline_cancels_children is disabled' do + before do + stub_feature_flags(ci_parent_pipeline_cancels_children: false) + end + + it 'does not cancel child pipeline builds' do + create(:ci_build, :created, pipeline: child_pipeline) + create(:ci_build, :running, pipeline: child_pipeline) + + cancel_running + + latest_status_for_child = child_pipeline.statuses.pluck(:status) + expect(latest_status_for_child).not_to include('canceled') + expect(latest_status).to eq %w(canceled) + end + end + end + + context 'when cascade_to_children is false' do + let(:cascade_to_children) { false } + + subject(:cancel_running) { pipeline.cancel_running(cascade_to_children: cascade_to_children) } + + it 'does not cancel cancelable child pipeline builds' do + create(:ci_build, :created, pipeline: child_pipeline) + create(:ci_build, :running, pipeline: child_pipeline) + + cancel_running + + latest_status_for_child = child_pipeline.statuses.pluck(:status) + expect(latest_status_for_child).to eq %w(created running) + expect(latest_status).to eq %w(canceled) + end + + it 'does not cancel uncancelable child pipeline builds' do + create(:ci_build, :failed, pipeline: child_pipeline) + + cancel_running + + latest_status_for_child = child_pipeline.statuses.pluck(:status) + expect(latest_status_for_child).to eq %w(failed) + expect(latest_status).to eq %w(canceled) + end + + context 'when feature ci_parent_pipeline_cancels_children is disabled' do + before do + stub_feature_flags(ci_parent_pipeline_cancels_children: false) + end + + it 'cancels parent but not children pipeline builds' do + create(:ci_build, :created, pipeline: child_pipeline) + create(:ci_build, :running, pipeline: child_pipeline) + + cancel_running + + latest_status_for_child = child_pipeline.statuses.pluck(:status) + expect(latest_status_for_child).not_to include('canceled') + expect(latest_status).to eq %w(canceled) + end end end end diff --git a/spec/models/personal_access_token_spec.rb b/spec/models/personal_access_token_spec.rb index 69866d497a1..dc3c73f9498 100644 --- a/spec/models/personal_access_token_spec.rb +++ b/spec/models/personal_access_token_spec.rb @@ -251,7 +251,7 @@ RSpec.describe PersonalAccessToken do describe '.simple_sorts' do it 'includes overridden keys' do - expect(described_class.simple_sorts.keys).to include(*%w(expires_at_asc expires_at_desc)) + expect(described_class.simple_sorts.keys).to include(*%w(expires_at_asc expires_at_desc expires_at_asc_id_desc)) end end @@ -270,5 +270,13 @@ RSpec.describe PersonalAccessToken do expect(described_class.order_expires_at_desc).to match [later_token, earlier_token] end end + + describe '.order_expires_at_asc_id_desc' do + let_it_be(:earlier_token_2) { create(:personal_access_token, expires_at: 2.days.ago) } + + it 'returns ordered list in combination of expires_at ascending and id descending' do + expect(described_class.order_expires_at_asc_id_desc).to eq [earlier_token_2, earlier_token, later_token] + end + end end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 6d2ba66d5f4..b7f0e524844 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1792,9 +1792,10 @@ RSpec.describe User do describe '#generate_password' do it 'does not generate password by default' do - user = create(:user, password: 'abcdefghe') + password = User.random_password + user = create(:user, password: password) - expect(user.password).to eq('abcdefghe') + expect(user.password).to eq(password) end end @@ -5997,8 +5998,9 @@ RSpec.describe User do end context 'user with a bcrypt password hash' do - # Plaintext password 'eiFubohV6iro' - let(:encrypted_password) { '$2a$10$xLTxCKOa75IU4RQGqqOrTuZOgZdJEzfSzjG6ZSEi/C31TB/yLZYpi' } + # Manually set a 'known' encrypted password + let(:password) { User.random_password } + let(:encrypted_password) { Devise::Encryptor.digest(User, password) } let(:user) { create(:user, encrypted_password: encrypted_password) } shared_examples 'not re-encrypting with PBKDF2' do @@ -6010,7 +6012,9 @@ RSpec.describe User do end context 'using the wrong password' do + # password 'WRONG PASSWORD' will not match the bcrypt hash let(:password) { 'WRONG PASSWORD' } + let(:encrypted_password) { Devise::Encryptor.digest(User, User.random_password) } it { is_expected.to be_falsey } it_behaves_like 'not re-encrypting with PBKDF2' @@ -6026,8 +6030,6 @@ RSpec.describe User do end context 'using the correct password' do - let(:password) { 'eiFubohV6iro' } - it { is_expected.to be_truthy } it 'validates the password and re-encrypts with PBKDF2' do @@ -6061,8 +6063,11 @@ RSpec.describe User do end context 'user with password hash that is neither PBKDF2 nor BCrypt' do - let(:user) { create(:user, encrypted_password: '$argon2i$v=19$m=512,t=4,p=2$eM+ZMyYkpDRGaI3xXmuNcQ$c5DeJg3eb5dskVt1mDdxfw') } - let(:password) { 'password' } + # Manually calculated User.random_password + let(:password) { "gg_w215TmVXGWSt7RJKXwYTVz886f6SDM3zvzztaJf2mX9ttUE8gRkNJSbWyWRLqxz4LFzxBekPe75ydDcGauE9wqg-acKMRT-WpSYjTm1Rdx-tnssE7CQByJcnxwWNH" } + # Created with https://argon2.online/ using 'aaaaaaaa' as the salt + let(:encrypted_password) { "$argon2i$v=19$m=512,t=4,p=2$YWFhYWFhYWE$PvJscKO5XRlevcgRReUg6w" } + let(:user) { create(:user, encrypted_password: encrypted_password) } it { is_expected.to be_falsey } @@ -6079,7 +6084,7 @@ RSpec.describe User do # These entire test section can be removed once the :pbkdf2_password_encryption feature flag is removed. describe '#password=' do let(:user) { create(:user) } - let(:password) { 'Oot5iechahqu' } + let(:password) { User.random_password } def compare_bcrypt_password(user, password) Devise::Encryptor.compare(User, user.encrypted_password, password) diff --git a/spec/presenters/project_hook_presenter_spec.rb b/spec/presenters/project_hook_presenter_spec.rb index 2e4bd17bbe1..a85865652d8 100644 --- a/spec/presenters/project_hook_presenter_spec.rb +++ b/spec/presenters/project_hook_presenter_spec.rb @@ -18,10 +18,10 @@ RSpec.describe ProjectHookPresenter do end describe '#logs_retry_path' do - subject { web_hook.present.logs_details_path(web_hook_log) } + subject { web_hook.present.logs_retry_path(web_hook_log) } let(:expected_path) do - "/#{project.namespace.path}/#{project.name}/-/hooks/#{web_hook.id}/hook_logs/#{web_hook_log.id}" + "/#{project.namespace.path}/#{project.name}/-/hooks/#{web_hook.id}/hook_logs/#{web_hook_log.id}/retry" end it { is_expected.to eq(expected_path) } diff --git a/spec/serializers/group_access_token_entity_spec.rb b/spec/serializers/group_access_token_entity_spec.rb new file mode 100644 index 00000000000..39b587c7df7 --- /dev/null +++ b/spec/serializers/group_access_token_entity_spec.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GroupAccessTokenEntity do + let_it_be(:group) { create(:group) } + let_it_be(:bot) { create(:user, :project_bot) } + let_it_be(:token) { create(:personal_access_token, user: bot) } + + subject(:json) { described_class.new(token, group: group).as_json } + + context 'when bot is a member of the group' do + before do + group.add_developer(bot) + end + + it 'has the correct attributes' do + expected_revoke_path = Gitlab::Routing.url_helpers + .revoke_group_settings_access_token_path( + { id: token, + group_id: group.path }) + + expect(json).to( + include( + id: token.id, + name: token.name, + scopes: token.scopes, + user_id: token.user_id, + revoke_path: expected_revoke_path, + access_level: ::Gitlab::Access::DEVELOPER + )) + + expect(json).not_to include(:token) + end + end + + context 'when bot is unrelated to the group' do + it 'has the correct attributes' do + expected_revoke_path = Gitlab::Routing.url_helpers + .revoke_group_settings_access_token_path( + { id: token, + group_id: group.path }) + + expect(json).to( + include( + id: token.id, + name: token.name, + scopes: token.scopes, + user_id: token.user_id, + revoke_path: expected_revoke_path, + access_level: nil + )) + + expect(json).not_to include(:token) + end + end +end diff --git a/spec/serializers/group_access_token_serializer_spec.rb b/spec/serializers/group_access_token_serializer_spec.rb new file mode 100644 index 00000000000..3b12c3115c9 --- /dev/null +++ b/spec/serializers/group_access_token_serializer_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GroupAccessTokenSerializer do + let_it_be(:group) { create(:group) } + let_it_be(:bot) { create(:user, :project_bot) } + + subject(:serializer) { described_class.new } + + before do + group.add_developer(bot) + end + + describe '#represent' do + it 'can render a single token' do + token = create(:personal_access_token, user: bot) + + expect(serializer.represent(token, group: group)).to be_kind_of(Hash) + end + + it 'can render a collection of tokens' do + tokens = create_list(:personal_access_token, 2, user: bot) + + expect(serializer.represent(tokens, group: group)).to be_kind_of(Array) + end + end +end diff --git a/spec/serializers/personal_access_token_entity_spec.rb b/spec/serializers/personal_access_token_entity_spec.rb new file mode 100644 index 00000000000..8a77a4e0036 --- /dev/null +++ b/spec/serializers/personal_access_token_entity_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe PersonalAccessTokenEntity do + let_it_be(:user) { create(:user) } + let_it_be(:token) { create(:personal_access_token, user: user) } + + subject(:json) { described_class.new(token).as_json } + + it 'has the correct attributes' do + expected_revoke_path = Gitlab::Routing.url_helpers + .revoke_profile_personal_access_token_path( + { id: token }) + + expect(json).to( + include( + id: token.id, + name: token.name, + scopes: token.scopes, + user_id: token.user_id, + revoke_path: expected_revoke_path + )) + + expect(json).not_to include(:token) + end +end diff --git a/spec/serializers/personal_access_token_serializer_spec.rb b/spec/serializers/personal_access_token_serializer_spec.rb new file mode 100644 index 00000000000..e4adc6abccb --- /dev/null +++ b/spec/serializers/personal_access_token_serializer_spec.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe PersonalAccessTokenSerializer do + subject(:serializer) { described_class.new } + + describe '#represent' do + it 'can render a single token' do + token = create(:personal_access_token) + + expect(serializer.represent(token)).to be_kind_of(Hash) + end + + it 'can render a collection of tokens' do + tokens = create_list(:personal_access_token, 2) + + expect(serializer.represent(tokens)).to be_kind_of(Array) + end + end +end diff --git a/spec/serializers/project_access_token_entity_spec.rb b/spec/serializers/project_access_token_entity_spec.rb new file mode 100644 index 00000000000..616aa45e9d5 --- /dev/null +++ b/spec/serializers/project_access_token_entity_spec.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe ProjectAccessTokenEntity do + let_it_be(:project) { create(:project) } + let_it_be(:bot) { create(:user, :project_bot) } + let_it_be(:token) { create(:personal_access_token, user: bot) } + + subject(:json) { described_class.new(token, project: project).as_json } + + context 'when bot is a member of the project' do + before do + project.add_developer(bot) + end + + it 'has the correct attributes' do + expected_revoke_path = Gitlab::Routing.url_helpers + .revoke_namespace_project_settings_access_token_path( + { id: token, + namespace_id: project.namespace.path, + project_id: project.path }) + + expect(json).to( + include( + id: token.id, + name: token.name, + scopes: token.scopes, + user_id: token.user_id, + revoke_path: expected_revoke_path, + access_level: ::Gitlab::Access::DEVELOPER + )) + + expect(json).not_to include(:token) + end + end + + context 'when bot is unrelated to the project' do + let_it_be(:project) { create(:project) } + + it 'has the correct attributes' do + expected_revoke_path = Gitlab::Routing.url_helpers + .revoke_namespace_project_settings_access_token_path( + { id: token, + namespace_id: project.namespace.path, + project_id: project.path }) + + expect(json).to( + include( + id: token.id, + name: token.name, + scopes: token.scopes, + user_id: token.user_id, + revoke_path: expected_revoke_path, + access_level: nil + )) + + expect(json).not_to include(:token) + end + end +end diff --git a/spec/serializers/project_access_token_serializer_spec.rb b/spec/serializers/project_access_token_serializer_spec.rb new file mode 100644 index 00000000000..1c0898d7841 --- /dev/null +++ b/spec/serializers/project_access_token_serializer_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe ProjectAccessTokenSerializer do + let_it_be(:project) { create(:project) } + let_it_be(:bot) { create(:user, :project_bot) } + + subject(:serializer) { described_class.new } + + before do + project.add_developer(bot) + end + + describe '#represent' do + it 'can render a single token' do + token = create(:personal_access_token, user: bot) + + expect(serializer.represent(token, project: project)).to be_kind_of(Hash) + end + + it 'can render a collection of tokens' do + tokens = create_list(:personal_access_token, 2, user: bot) + + expect(serializer.represent(tokens, project: project)).to be_kind_of(Array) + end + end +end diff --git a/spec/services/ci/destroy_pipeline_service_spec.rb b/spec/services/ci/destroy_pipeline_service_spec.rb index 045051c7152..6bd7fe7559c 100644 --- a/spec/services/ci/destroy_pipeline_service_spec.rb +++ b/spec/services/ci/destroy_pipeline_service_spec.rb @@ -90,15 +90,23 @@ RSpec.describe ::Ci::DestroyPipelineService do end end - context 'when pipeline is in cancelable state' do - before do - allow(pipeline).to receive(:cancelable?).and_return(true) - end + context 'when pipeline is in cancelable state', :sidekiq_inline do + let!(:build) { create(:ci_build, :running, pipeline: pipeline) } + let!(:child_pipeline) { create(:ci_pipeline, :running, child_of: pipeline) } + let!(:child_build) { create(:ci_build, :running, pipeline: child_pipeline) } - it 'cancels the pipeline' do - expect(pipeline).to receive(:cancel_running) + it 'cancels the pipelines sync' do + # turn off deletion for all instances of pipeline to allow for testing cancellation + allow(pipeline).to receive_message_chain(:reset, :destroy!) + allow_next_found_instance_of(Ci::Pipeline) { |p| allow(p).to receive_message_chain(:reset, :destroy!) } + + # ensure cancellation happens sync so we accumulate minutes + expect(::Ci::CancelPipelineWorker).not_to receive(:perform) subject + + expect(build.reload.status).to eq('canceled') + expect(child_build.reload.status).to eq('canceled') end end end diff --git a/spec/support/helpers/features/blob_spec_helpers.rb b/spec/support/helpers/features/blob_spec_helpers.rb index 880a7249284..7ccfc9be7e2 100644 --- a/spec/support/helpers/features/blob_spec_helpers.rb +++ b/spec/support/helpers/features/blob_spec_helpers.rb @@ -11,12 +11,4 @@ module BlobSpecHelpers def unset_default_button set_default_button('') end - - def editor_value - evaluate_script('monaco.editor.getModels()[0].getValue()') - end - - def set_editor_value(value) - execute_script("monaco.editor.getModels()[0].setValue('#{value}')") - end end diff --git a/spec/support/helpers/features/source_editor_spec_helpers.rb b/spec/support/helpers/features/source_editor_spec_helpers.rb index cdc59f9cbe1..a065ead622e 100644 --- a/spec/support/helpers/features/source_editor_spec_helpers.rb +++ b/spec/support/helpers/features/source_editor_spec_helpers.rb @@ -12,8 +12,7 @@ module Spec def editor_set_value(value) editor = find('.monaco-editor') uri = editor['data-uri'] - - execute_script("monaco.editor.getModel('#{uri}').setValue('#{escape_javascript(value)}')") + execute_script("localMonaco.getModel('#{uri}').setValue('#{escape_javascript(value)}')") end end end diff --git a/spec/workers/ci/cancel_pipeline_worker_spec.rb b/spec/workers/ci/cancel_pipeline_worker_spec.rb new file mode 100644 index 00000000000..6165aaff1c7 --- /dev/null +++ b/spec/workers/ci/cancel_pipeline_worker_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Ci::CancelPipelineWorker, :aggregate_failures do + let!(:pipeline) { create(:ci_pipeline, :running) } + + describe '#perform' do + subject(:perform) { described_class.new.perform(pipeline.id, pipeline.id) } + + it 'calls cancel_running' do + allow(::Ci::Pipeline).to receive(:find_by_id).and_return(pipeline) + expect(pipeline).to receive(:cancel_running).with( + auto_canceled_by_pipeline_id: pipeline.id, + cascade_to_children: false + ) + + perform + end + + context 'if pipeline is deleted' do + subject(:perform) { described_class.new.perform(non_existing_record_id, non_existing_record_id) } + + it 'does not error' do + expect(pipeline).not_to receive(:cancel_running) + + perform + end + end + + describe 'with builds and state transition side effects', :sidekiq_inline do + let!(:build) { create(:ci_build, :running, pipeline: pipeline) } + + it_behaves_like 'an idempotent worker', :sidekiq_inline do + let(:job_args) { [pipeline.id, pipeline.id] } + + it 'cancels the pipeline' do + perform + + pipeline.reload + + expect(pipeline).to be_canceled + expect(pipeline.builds.first).to be_canceled + expect(pipeline.builds.first.auto_canceled_by_id).to eq pipeline.id + expect(pipeline.auto_canceled_by_id).to eq pipeline.id + end + end + end + end +end diff --git a/yarn.lock b/yarn.lock index 0bde7e30e0a..e561f349429 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2576,13 +2576,6 @@ acorn@^8.0.4, acorn@^8.7.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== -agent-base@4, agent-base@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" - integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== - dependencies: - es6-promisify "^5.0.0" - aggregate-error@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" @@ -4780,14 +4773,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: dependencies: ms "2.0.0" -debug@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - -debug@^3.1.0, debug@^3.2.6, debug@^3.2.7: +debug@^3.2.6, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -5331,23 +5317,11 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" -es6-promise@^4.0.3: - version "4.2.8" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" - integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== - es6-promise@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.0.2.tgz#010d5858423a5f118979665f46486a95c6ee2bb6" integrity sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y= -es6-promisify@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" - integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= - dependencies: - es6-promise "^4.0.3" - escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -6845,14 +6819,6 @@ http-parser-js@>=0.5.1: resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9" integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg== -http-proxy-agent@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" - integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg== - dependencies: - agent-base "4" - debug "3.1.0" - http-proxy-middleware@^2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.4.tgz#03af0f4676d172ae775cb5c33f592f40e1a4e07a" @@ -6887,14 +6853,6 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= -https-proxy-agent@^2.2.3: - version "2.2.4" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" - integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg== - dependencies: - agent-base "^4.3.0" - debug "^3.1.0" - human-signals@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" @@ -7961,7 +7919,7 @@ js-cookie@^3.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@^3.13.1: +js-yaml@^3.13.1, js-yaml@^3.14.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== @@ -8105,11 +8063,6 @@ json5@^2.1.2, json5@^2.2.1: resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== -jsonc-parser@^2.2.1, jsonc-parser@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.3.1.tgz#59549150b133f2efacca48fe9ce1ec0659af2342" - integrity sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg== - jsonc-parser@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.0.0.tgz#abdd785701c7e7eaca8a9ec8cf070ca51a745a22" @@ -9397,24 +9350,26 @@ moment-mini@^2.24.0: resolved "https://registry.yarnpkg.com/moment-mini/-/moment-mini-2.24.0.tgz#fa68d98f7fe93ae65bf1262f6abb5fb6983d8d18" integrity sha512-9ARkWHBs+6YJIvrIp0Ik5tyTTtP9PoV0Ssu2Ocq5y9v8+NOOpWiRshAp8c4rZVWTOe+157on/5G+zj5pwIQFEQ== -monaco-editor-webpack-plugin@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-4.0.0.tgz#95be3f48f4220999b909266a9997727f0deab947" - integrity sha512-4BT9XDRQXraMQjxEUjR+uuubRe3RIPkvVoGw8zwWG++s7wq6TAiXaSOMdkdS9TrjCREgSnygCOlVzY6MS8RPuA== +monaco-editor-webpack-plugin@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-4.2.0.tgz#2be76cde9cca7bd8c3418503625990f86886927b" + integrity sha512-/P3sFiEgBl+Y50he4mbknMhbLJVop5gBUZiPS86SuHUDOOnQiQ5rL1jU5lwt1XKAwMEkhwZbUwqaHxTPkb1Utw== dependencies: loader-utils "^2.0.0" -monaco-editor@^0.25.2: - version "0.25.2" - resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.25.2.tgz#119e2b15bbd968a1a99c03cac9c329316d7c37e9" - integrity sha512-5iylzSJevCnzJn9UVsW8yOZ3yHjmAs4TfvH3zsbftKiFKmHG0xirGN6DK9Kk04VSWxYCZZAIafYJoNJJMAU1KA== +monaco-editor@^0.28.0: + version "0.28.1" + resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.28.1.tgz#732788ff2172d59e6d436b206da8cac715413940" + integrity sha512-P1vPqxB4B1ZFzTeR1ScggSp9/5NoQrLCq88fnlNUsuRAP1usEBN4TIpI2lw0AYIZNVIanHk0qwjze2uJwGOHUw== -monaco-yaml@^2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/monaco-yaml/-/monaco-yaml-2.5.1.tgz#af9303a4aa6e3b94db62b8a8659362f31944590d" - integrity sha512-U+zIAcwnQzlUgy6vdzFdNf5PToFzuz099FxYmUxIeen9GTiq6XYDX9mmXSR31mMrgiSaU5a2bGEyG4p2fbW/7A== +monaco-yaml@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/monaco-yaml/-/monaco-yaml-3.0.0.tgz#b3d59c3485bd5a161438072a8e5a8aaf74041dfd" + integrity sha512-WkgdfjCj0L2VPPwPoiwc4l8+B78FyVpSsMoufEWqe3ukm8+WygKUtmtCFOFnehmMih6tSqhy4DUtoAhfnicyZA== dependencies: - yaml-language-server "^0.11.1" + "@types/json-schema" "^7.0.8" + js-yaml "^3.14.1" + yaml-ast-parser-custom-tags "^0.0.43" mousetrap@1.6.5: version "1.6.5" @@ -10301,11 +10256,6 @@ pretender@^3.4.3: fake-xml-http-request "^2.1.1" route-recognizer "^0.3.3" -prettier@2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4" - integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg== - prettier@2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5" @@ -10933,15 +10883,6 @@ repeat-string@^1.6.1: resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= -request-light@^0.2.4: - version "0.2.5" - resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.2.5.tgz#38a3da7b2e56f7af8cbba57e8a94930ee2380746" - integrity sha512-eBEh+GzJAftUnex6tcL6eV2JCifY0+sZMIUpUPOVXbs2nV5hla4ZMmO3icYKGuGVuQ2zHE9evh4OrRcH4iyYYw== - dependencies: - http-proxy-agent "^2.1.0" - https-proxy-agent "^2.2.3" - vscode-nls "^4.1.1" - request-promise-core@1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" @@ -12852,78 +12793,6 @@ vm-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.0.tgz#bd76d6a23323e2ca8ffa12028dc04559c75f9019" integrity sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw== -vscode-json-languageservice@^3.6.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.9.1.tgz#f72b581f8cd2bd9b47445ccf8b0ddcde6aba7483" - integrity sha512-oJkknkdCVitQ5XPSRa0weHjUxt8eSCptaL+MBQQlRsa6Nb8XnEY0S5wYnLUFHzEvKzwt01/LKk8LdOixWEXkNA== - dependencies: - jsonc-parser "^2.3.1" - vscode-languageserver-textdocument "^1.0.1" - vscode-languageserver-types "3.16.0-next.2" - vscode-nls "^5.0.0" - vscode-uri "^2.1.2" - -vscode-jsonrpc@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz#a7bf74ef3254d0a0c272fab15c82128e378b3be9" - integrity sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg== - -vscode-languageserver-protocol@3.14.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.14.1.tgz#b8aab6afae2849c84a8983d39a1cf742417afe2f" - integrity sha512-IL66BLb2g20uIKog5Y2dQ0IiigW0XKrvmWiOvc0yXw80z3tMEzEnHjaGAb3ENuU7MnQqgnYJ1Cl2l9RvNgDi4g== - dependencies: - vscode-jsonrpc "^4.0.0" - vscode-languageserver-types "3.14.0" - -vscode-languageserver-textdocument@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz#178168e87efad6171b372add1dea34f53e5d330f" - integrity sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA== - -vscode-languageserver-types@3.14.0: - version "3.14.0" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz#d3b5952246d30e5241592b6dde8280e03942e743" - integrity sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A== - -vscode-languageserver-types@3.16.0-next.2: - version "3.16.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.2.tgz#940bd15c992295a65eae8ab6b8568a1e8daa3083" - integrity sha512-QjXB7CKIfFzKbiCJC4OWC8xUncLsxo19FzGVp/ADFvvi87PlmBSCAtZI5xwGjF5qE0xkLf0jjKUn3DzmpDP52Q== - -vscode-languageserver-types@^3.15.1: - version "3.15.1" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz#17be71d78d2f6236d414f0001ce1ef4d23e6b6de" - integrity sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ== - -vscode-languageserver@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-5.2.1.tgz#0d2feddd33f92aadf5da32450df498d52f6f14eb" - integrity sha512-GuayqdKZqAwwaCUjDvMTAVRPJOp/SLON3mJ07eGsx/Iq9HjRymhKWztX41rISqDKhHVVyFM+IywICyZDla6U3A== - dependencies: - vscode-languageserver-protocol "3.14.1" - vscode-uri "^1.0.6" - -vscode-nls@^4.1.1, vscode-nls@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.2.tgz#ca8bf8bb82a0987b32801f9fddfdd2fb9fd3c167" - integrity sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw== - -vscode-nls@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.0.0.tgz#99f0da0bd9ea7cda44e565a74c54b1f2bc257840" - integrity sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA== - -vscode-uri@^1.0.6: - version "1.0.8" - resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.8.tgz#9769aaececae4026fb6e22359cb38946580ded59" - integrity sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ== - -vscode-uri@^2.1.1, vscode-uri@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.1.2.tgz#c8d40de93eb57af31f3c715dd650e2ca2c096f1c" - integrity sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A== - vue-apollo@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/vue-apollo/-/vue-apollo-3.0.7.tgz#97a031d45641faa4888a6d5a7f71c40834359704" @@ -13481,28 +13350,11 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml-ast-parser-custom-tags@0.0.43: +yaml-ast-parser-custom-tags@^0.0.43: version "0.0.43" resolved "https://registry.yarnpkg.com/yaml-ast-parser-custom-tags/-/yaml-ast-parser-custom-tags-0.0.43.tgz#46968145ce4e24cb03c3312057f0f141b93a7d02" integrity sha512-R5063FF/JSAN6qXCmylwjt9PcDH6M0ExEme/nJBzLspc6FJDmHHIqM7xh2WfEmsTJqClF79A9VkXjkAqmZw9SQ== -yaml-language-server@^0.11.1: - version "0.11.1" - resolved "https://registry.yarnpkg.com/yaml-language-server/-/yaml-language-server-0.11.1.tgz#4ddc72eb9a6dd7dc41f31af2a8f5c72cce456cc9" - integrity sha512-N3Tu3g4O6ZWV7W0LVsNk62DtKJDQkbnPZRDd7ntaAeEl8QkxL1vnMunI26uzDU4PwwG4tPJ8g/VRS6U+fVp/6A== - dependencies: - js-yaml "^3.13.1" - jsonc-parser "^2.2.1" - request-light "^0.2.4" - vscode-json-languageservice "^3.6.0" - vscode-languageserver "^5.2.1" - vscode-languageserver-types "^3.15.1" - vscode-nls "^4.1.2" - vscode-uri "^2.1.1" - yaml-ast-parser-custom-tags "0.0.43" - optionalDependencies: - prettier "2.0.5" - yaml@^1.10.0: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"